nouveau fichier : CMakeLists.txt
nouveau fichier : CMakeListsOTB.txt nouveau fichier : Readme.html nouveau fichier : include/Attribute.hpp nouveau fichier : include/Attributes/AreaAttribute.hpp nouveau fichier : include/BuildTree.hpp nouveau fichier : include/DAPTree/Border.hpp nouveau fichier : include/DAPTree/DAPTreeBuilder.hpp nouveau fichier : include/DAPTree/DAPTreeBuilder.tpp nouveau fichier : include/DAPTree/GraphWalker.hpp nouveau fichier : include/DAPTree/ParRnk.hpp nouveau fichier : include/DAPTree/Weight.hpp nouveau fichier : include/DAPTree/baseDAPTree.hpp nouveau fichier : include/DAPTree/sort.hpp nouveau fichier : include/ImageInterface.hpp nouveau fichier : include/ImageInterface.tpp nouveau fichier : include/QuadTree/QuadTreeBuilder.hpp nouveau fichier : include/Tree.hpp nouveau fichier : include/TreeOfShapesGeraud/ToSBuilder.hpp nouveau fichier : include/TreeOfShapesGeraud/ToSutils.hpp nouveau fichier : include/XMLTree/XMLTreeBuilder.hpp nouveau fichier : include/baseDef.hpp nouveau fichier : include/dealThreads.hpp nouveau fichier : include/debug.hpp nouveau fichier : include/getType.hpp nouveau fichier : otb-module.cmake nouveau fichier : src/Attribute.cpp nouveau fichier : src/Attributes/AreaAttribute.cpp nouveau fichier : src/CMakeLists.txt nouveau fichier : src/DAPTree/GraphWalker.cpp nouveau fichier : src/DAPTree/ParRnk.cpp nouveau fichier : src/DAPTree/baseDAPTree.cpp nouveau fichier : src/DAPTree/sort.cpp nouveau fichier : src/QuadTree/QuadTreeBuilder.cpp nouveau fichier : src/Tree.cpp nouveau fichier : src/TreeOfShapesGeraud/ToSBuilder.cpp nouveau fichier : src/TreeOfShapesGeraud/ToSutils.cpp nouveau fichier : src/XMLTree/XMLTreeBuilder.cpp nouveau fichier : src/debug.cpp nouveau fichier : src/testMain.cpp nouveau fichier : tests/ToSGeraudCoord.txt nouveau fichier : tests/ToSGeraudIdx.ods
This commit is contained in:
parent
98823f5f30
commit
bc00fd7cbc
32
CMakeLists.txt
Normal file
32
CMakeLists.txt
Normal file
@ -0,0 +1,32 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(TreeBuilder)
|
||||
|
||||
set(OUT_NAME "TreeBuilder")
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -pthread -Wall -g") #-Wshadow")
|
||||
|
||||
set(TREEBUILDER_INCLUDES include)
|
||||
|
||||
file(GLOB_RECURSE TREEBUILDER_SOURCES src/*.cpp)
|
||||
|
||||
find_package(OTB)
|
||||
|
||||
find_package(OpenCV REQUIRED) # Petra
|
||||
|
||||
if(OTB_FOUND)
|
||||
include(${OTB_USE_FILE})
|
||||
else(OTB_FOUND)
|
||||
message(FATAL_ERROR
|
||||
"Cannot build OTB project without OTB. Please set OTB_DIR.")
|
||||
endif(OTB_FOUND)
|
||||
|
||||
include_directories(${OTB_INCLUDES})
|
||||
include_directories(${TREEBUILDER_INCLUDES})
|
||||
|
||||
set(TREEBUILDER_LIBS tinyxml opencv_ml opencv_core boost_system boost_thread)
|
||||
|
||||
# Ajout de l'exec / lib
|
||||
add_executable(${OUT_NAME} ${TREEBUILDER_SOURCES})
|
||||
|
||||
target_link_libraries(${OUT_NAME} ${TREEBUILDER_LIBS} ${OpenCV_LIBS} ${OTB_LIBRARIES})
|
13
CMakeListsOTB.txt
Normal file
13
CMakeListsOTB.txt
Normal file
@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 2.8.9)
|
||||
|
||||
project(OTBTreeBuilder)
|
||||
|
||||
set(OTBTreeBuilder_LIBRARIES OTBTreeBuilder)
|
||||
|
||||
if(NOT OTB_SOURCE_DIR)
|
||||
find_package(OTB REQUIRED)
|
||||
list(APPEND CMAKE_MODULE_PATH ${OTB_CMAKE_DIR})
|
||||
include(OTBModuleExternal)
|
||||
else()
|
||||
otb_module_impl()
|
||||
endif()
|
1
Readme.html
Normal file
1
Readme.html
Normal file
@ -0,0 +1 @@
|
||||
TRISKELE est l'abréviation de « Tree Representations of Images for Scalable Knowledge Extraction and Learning for Earth observation ».
|
46
include/Attribute.hpp
Normal file
46
include/Attribute.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef ATTRIBUTE_HPP
|
||||
#define ATTRIBUTE_HPP
|
||||
|
||||
#include "Tree.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
/**
|
||||
* Attribute
|
||||
*/
|
||||
|
||||
class Attribute {
|
||||
public:
|
||||
Attribute();
|
||||
Attribute(const Attribute &o) = delete;
|
||||
|
||||
void
|
||||
setTree(Tree &treeC);
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
free();
|
||||
|
||||
template<typename T>
|
||||
T
|
||||
getAttribute(const DimNodeId &nodeId);
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
generate();
|
||||
|
||||
protected:
|
||||
virtual void
|
||||
generate() = 0;
|
||||
|
||||
protected:
|
||||
Tree *tree;
|
||||
|
||||
void *attributes;
|
||||
};
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // ATTRIBUTE_HPP
|
24
include/Attributes/AreaAttribute.hpp
Normal file
24
include/Attributes/AreaAttribute.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#ifndef AREAATTRIBUTE_HPP
|
||||
#define AREAATTRIBUTE_HPP
|
||||
|
||||
#include "Attribute.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
/**
|
||||
* AreaAttribute
|
||||
*/
|
||||
|
||||
class AreaAttribute : Attribute {
|
||||
public:
|
||||
void
|
||||
generate();
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // AREAATTRIBUTE_HPP
|
47
include/BuildTree.hpp
Normal file
47
include/BuildTree.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef BUILDOTREE_HPP
|
||||
#define BUILDOTREE_HPP
|
||||
|
||||
#include "Tree.hpp"
|
||||
#include "baseDef.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
class BuildTree {
|
||||
public:
|
||||
|
||||
|
||||
static void
|
||||
buildTree(Tree &tree, BuildTree &builder) { builder.buildTree(tree); }
|
||||
|
||||
static void
|
||||
buildTree(Tree &tree, BuildTree &&builder) { builder.buildTree(tree); }
|
||||
|
||||
virtual void
|
||||
buildTree(Tree &tree) { std::cout << "Test" << std::endl; }
|
||||
|
||||
protected:
|
||||
// Used to set the attributes below with the tree
|
||||
|
||||
inline void updateAttributes(Tree &tree) {
|
||||
leafParents = tree.leafParents;
|
||||
compParents = tree.compParents;
|
||||
children = tree.children;
|
||||
childCount = tree.childCount;
|
||||
newCompIndex = tree.newCompIndex;
|
||||
}
|
||||
|
||||
protected:
|
||||
// Attributes corresponding to the tree, used to make the construction easier
|
||||
|
||||
/*! Pointers on the parents of each leafs / nodes */
|
||||
DimNodeId *leafParents, *compParents;
|
||||
|
||||
/*! Pointers on the children and count how many children a parents have */
|
||||
DimNodeId *children, *childCount, *childCountRec;
|
||||
|
||||
DimNodeId *newCompIndex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // BUILDOTREE_HPP
|
88
include/DAPTree/Border.hpp
Normal file
88
include/DAPTree/Border.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef BORDER_HPP
|
||||
#define BORDER_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "baseDef.hpp"
|
||||
#include "baseDAPTree.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
/**
|
||||
* Border
|
||||
*/
|
||||
|
||||
class Border {
|
||||
public:
|
||||
/*! Retourne le nombre de pixels à l'aide de la taille */
|
||||
static DimImg getPixelsCount (const Size &size) { return DimImg (size.width)*DimImg (size.height); }
|
||||
|
||||
/*! Retourne la taille que doit faire le tableau simplifié */
|
||||
static DimImg getMapLength (DimImg pixelsCount) { return (pixelsCount+7)/8; }
|
||||
|
||||
/*! Vérifie si un index est sur la map ou une bordure, en se basant sur le bit de l'index idx de la map */
|
||||
bool isBorder (DimImg idx) const { return map ? map[idx/8] & (1 << (idx%8)) : false; }
|
||||
|
||||
/*! Vérifie si un point est sur la map ou une bordure en appelant la méthode précédente après avoir converti le point en index */
|
||||
bool isBorder (const Point &p) const { return map ? isBorder (pointToId (size, p)) : false; }
|
||||
|
||||
/*! Supprime toutes les occurences de bordure à l'index idx */
|
||||
void clearBorder (DimImg idx) { map[idx/8] &= ~(1 << (idx%8)); }
|
||||
|
||||
/*! Supprime toutes les occurences de bordure en appelant la méthode précédente après avoir converti le point en index */
|
||||
void clearBorder (const Point &p) { clearBorder (pointToId (size, p)); }
|
||||
|
||||
/*! Rajoute une occurence de bordure à l'index indiqué */
|
||||
void setBorder (DimImg idx) { map[idx/8] |= (1 << (idx%8)); }
|
||||
|
||||
/*! Rajoute une occurence de bordure en appelant la méthode précédente après avoir converti le point en index */
|
||||
void setBorder (const Point &p) { setBorder (pointToId (size, p)); }
|
||||
|
||||
/*! Construit par défault sans aucune bordure */
|
||||
Border ()
|
||||
: pixelsCount (0), mapLength (0), size (), map (NULL) {
|
||||
}
|
||||
|
||||
/*! Construit Border, les valeurs de map dépendent de defaultVal */
|
||||
Border (const Size &size, bool defaultVal)
|
||||
: pixelsCount (getPixelsCount (size)), mapLength (getMapLength (pixelsCount)), size (size) {
|
||||
map = new uint8_t [mapLength];
|
||||
reset (defaultVal);
|
||||
}
|
||||
~Border () { if (map) delete [] map; }
|
||||
|
||||
void reset (bool defaultVal) {
|
||||
std::fill_n (map, mapLength, defaultVal ? 0xFF : 0);
|
||||
if (!(mapLength && defaultVal))
|
||||
return;
|
||||
map[mapLength-1] &= 0xFF >> (8-(pixelsCount%8))%8;
|
||||
}
|
||||
|
||||
/*! Compte le nombre de pixels considérés comme de la bordure */
|
||||
DimImg borderCount () {
|
||||
DimImg result = 0;
|
||||
for (DimImg i = 0; i < mapLength; ++i)
|
||||
result += bitCount[map[i]];
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/*! Nombre de pixels dans l'image */
|
||||
DimImg pixelsCount;
|
||||
|
||||
/*! Taille du tableau "simplifié" des pixels */
|
||||
DimImg mapLength;
|
||||
|
||||
/*! Dimensions de l'image */
|
||||
Size size;
|
||||
|
||||
/*! Tableau "simplifié" des pixels */
|
||||
uint8_t *map;
|
||||
};
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // BORDER_HPP
|
123
include/DAPTree/DAPTreeBuilder.hpp
Normal file
123
include/DAPTree/DAPTreeBuilder.hpp
Normal file
@ -0,0 +1,123 @@
|
||||
#ifndef DAPTREE_HPP
|
||||
#define DAPTREE_HPP
|
||||
|
||||
#include "BuildTree.hpp"
|
||||
#include "ImageInterface.hpp"
|
||||
#include "debug.hpp"
|
||||
#include "sort.hpp"
|
||||
#include "dealThreads.hpp"
|
||||
#include "GraphWalker.hpp"
|
||||
#include "Weight.hpp"
|
||||
#include "ParRnk.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
template <typename WeightT>
|
||||
class DAPTreeBuilder : public BuildTree {
|
||||
public:
|
||||
inline DAPTreeBuilder(ImageInterface &imgInt, const TreeType &treeType, const bool &countingSort = true) : image(imgInt),
|
||||
type(treeType),
|
||||
countingFlag(countingSort) {}
|
||||
|
||||
inline void
|
||||
buildTree(Tree &tree);
|
||||
|
||||
private:
|
||||
|
||||
inline void
|
||||
setTiles (const Size &size, const unsigned int &coreCount, const Rect &tile,
|
||||
std::vector<Rect> &tiles, std::vector<Rect> &boundaries, std::vector<bool> &verticalBoundaries);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
buildTree (Tree &tree, const GraphWalker &graphWalker, const WeightFunct &weightFunct, const bool &countingSortFlag);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
buildTree (Edge<WeightT> *edges, const GraphWalker &graphWalker, const WeightFunct &weightFunct,
|
||||
const Rect &tile, DimImg &topParent, const bool &countingSortFlag);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
createAttributsProfile (const WeightFunct &weightFunct);
|
||||
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
connectLeaf (Tree &tree, DimImg a, DimImg b, const WeightT &weight, DimImg &parCount, const WeightFunct &weightFunct);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
connectComp (DimImg newComp, DimImg topA, DimImg topB, const WeightFunct &weightFunct);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
connectComp (DimImg topA, DimImg topB, const WeightFunct &weightFunct);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline DimImg
|
||||
updateNewIdx (const std::vector<DimImg> &compBases, const std::vector<DimImg> &compTops, const WeightFunct &weightFunct);
|
||||
|
||||
inline void
|
||||
updateNewIdx (Tree &tree, const DimImg curComp, DimImg &compCount);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
compress(const GraphWalker &graphWalker, const Rect &tile,
|
||||
const DimImg &compBase, const DimImg &compTop,
|
||||
const WeightFunct &weightFunct);
|
||||
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline DimImg
|
||||
findTopComp (Tree &tree, const DimImg &comp, const WeightFunct &weightFunct);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline DimImg
|
||||
findTopComp (DimImg comp, const WeightT &weight, const WeightFunct &weightFunct);
|
||||
|
||||
inline DimImg
|
||||
findCompMultiChild (DimImg comp);
|
||||
|
||||
inline DimImg
|
||||
createComp(Tree &tree, const DimImg &leadPixel, const WeightT &weight, DimImg &compTop, const DimNodeId &childCount);
|
||||
|
||||
inline void
|
||||
linkParent (Tree &tree, const DimImg &pixel, const DimImg &parent);
|
||||
|
||||
inline void
|
||||
buildChildren (Tree &tree);
|
||||
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
initWeights (Tree &tree, const GraphWalker &graphWalker, const WeightFunct &weightFunct);
|
||||
|
||||
private:
|
||||
ImageInterface ℑ
|
||||
|
||||
DimNodeId *childCountRec;
|
||||
|
||||
DimNodeId nodeCapacity;
|
||||
|
||||
WeightT *compWeights; // [leafCount]
|
||||
|
||||
void *leafAP; // [nodeCapacity]
|
||||
|
||||
DimImg *newCompIdx;
|
||||
|
||||
ParRnk parRnk;
|
||||
|
||||
uint32_t *pixels;
|
||||
|
||||
TreeType type;
|
||||
|
||||
bool countingFlag;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
#include "DAPTreeBuilder.tpp"
|
||||
|
||||
#endif // DAPTREE_HPP
|
610
include/DAPTree/DAPTreeBuilder.tpp
Normal file
610
include/DAPTree/DAPTreeBuilder.tpp
Normal file
@ -0,0 +1,610 @@
|
||||
#ifdef SMART_LOG
|
||||
#include <iostream>
|
||||
#endif // SMART_LOG
|
||||
|
||||
#include "ImageInterface.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
template<typename WeightT>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::buildTree(Tree &tree) {
|
||||
switch(type) {
|
||||
case MIN:
|
||||
break;
|
||||
case MAX:
|
||||
break;
|
||||
case TOS:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::buildTree(Tree &tree, const GraphWalker &graphWalker, const WeightFunct &weightFunct, const bool &countingSortFlag) {
|
||||
DEF_LOG ("DapTree::buildTree", " counting:" << countingSortFlag << " vertexCount:" << graphWalker.vertexMaxCount () <<
|
||||
" countEdge:" << graphWalker.edgeMaxCount ());
|
||||
BOOST_ASSERT (newCompIdx == NULL);
|
||||
|
||||
// XXX
|
||||
unsigned int coreCount = 1;
|
||||
|
||||
tree.resize(graphWalker.vertexMaxCount());
|
||||
updateAttributes(tree);
|
||||
compWeights = new WeightT[tree.getLeafCount()];
|
||||
childCountRec = childCount + 2;
|
||||
|
||||
BOOST_ASSERT (tree.getLeafCount() == graphWalker.vertexMaxCount ());
|
||||
LOG ("leafCount:" << tree.getLeafCount());
|
||||
if (!tree.getLeafCount())
|
||||
return;
|
||||
|
||||
parRnk.book (tree.getLeafCount());
|
||||
newCompIdx = parRnk.getParent ();
|
||||
std::vector<Edge<WeightT> > allEdges (graphWalker.edgeMaxCount ());
|
||||
initWeights (graphWalker, weightFunct);
|
||||
|
||||
std::vector<Rect> tiles;
|
||||
std::vector<Rect> boundaries;
|
||||
std::vector<bool> verticalBoundaries;
|
||||
const Size &size (graphWalker.size);
|
||||
graphWalker.setTiles (coreCount, Rect (Point(), size), tiles, boundaries, verticalBoundaries);
|
||||
unsigned int tileCount = tiles.size ();
|
||||
unsigned int boundCount = boundaries.size ();
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "tile / bound" << std::endl;
|
||||
for (unsigned int i = 0; i < tileCount; ++i)
|
||||
std::cout << i << " tile: " << tiles [i] << std::endl;
|
||||
for (unsigned int i = 0; i < boundCount; ++i)
|
||||
std::cout << i << " bound: " << boundaries [i] << " " << (verticalBoundaries [i] ? "Vertical" : "Horizontal") << std::endl;
|
||||
#endif
|
||||
std::vector<Edge<WeightT> *> tileEdges (tileCount);
|
||||
std::vector<DimImg> compBases (tileCount);
|
||||
std::vector<DimImg> compTops (tileCount);
|
||||
DimImg compBase = 0;
|
||||
Edge<WeightT> *edgeBase = &allEdges[0];
|
||||
for (unsigned int i = 0; i < tileCount; ++i) {
|
||||
tileEdges [i] = edgeBase;
|
||||
Size zoneSize (tiles[i].width, tiles[i].height);
|
||||
edgeBase += graphWalker.edgeMaxCount (zoneSize);
|
||||
|
||||
compBases [i] = compBase;
|
||||
compTops [i] = compBase;
|
||||
compBase += graphWalker.vertexMaxCount (zoneSize); /* -1, but prety LOG */
|
||||
}
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "base / top" << std::endl;
|
||||
for (unsigned int i = 0; i < tileCount; ++i)
|
||||
std::cout << i << " base: " << compBases [i] << " top: " << compTops [i] << std::endl;
|
||||
#endif
|
||||
dealThreadRange (tileCount, coreCount, [this, &tileEdges, &graphWalker, &weightFunct, &tiles, &compTops, &countingSortFlag] (DimImg threadId) {
|
||||
buildTree (tileEdges [threadId], graphWalker, weightFunct, tiles [threadId], compTops [threadId], countingSortFlag);
|
||||
});
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "base / top" << std::endl;
|
||||
for (unsigned int i = 0; i < tileCount; ++i)
|
||||
std::cout << i << " base: " << compBases [i] << " top: " << compTops [i] << std::endl;
|
||||
|
||||
std::cout << "build tiles" << std::endl;
|
||||
//printParRnk (size);
|
||||
//printTree (size, true);
|
||||
#endif
|
||||
DimImg compCount = compTops [0];
|
||||
DimImg *topC = NULL;
|
||||
if (boundCount) {
|
||||
std::vector<Edge<WeightT> *> edgeBounds (boundCount);
|
||||
std::vector<DimImg> edgeCounts (boundCount);
|
||||
Edge<WeightT> *allBoundEdges = edgeBase;
|
||||
for (unsigned int i = 0; i < boundCount; ++i) {
|
||||
edgeBounds [i] = edgeBase;
|
||||
DimImg borderDim = verticalBoundaries [i] ? boundaries[i].height : boundaries[i].width;
|
||||
edgeBase += graphWalker.edgeBoundaryMaxCount (borderDim);
|
||||
}
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "boundBase" << std::endl;
|
||||
for (unsigned int i = 0; i < boundCount; ++i) {
|
||||
DimImg borderDim = verticalBoundaries [i] ? boundaries[i].height : boundaries[i].width;
|
||||
std::cout << i << " borderDim: " << borderDim
|
||||
<< " edgeCount:" << graphWalker.edgeBoundaryMaxCount (borderDim)
|
||||
<< " bound: " << boundaries [i] << " " << (verticalBoundaries [i] ? "Vertical" : "Horizontal") << std::endl;
|
||||
}
|
||||
#endif
|
||||
dealThreadRange (boundCount, coreCount, [&edgeCounts, &graphWalker, &boundaries, &verticalBoundaries, &edgeBounds, &weightFunct] (DimImg id) {
|
||||
edgeCounts [id] = graphWalker.getSortedEdges (boundaries [id], verticalBoundaries [id] ?
|
||||
Vertical : Horizontal, edgeBounds [id], weightFunct);
|
||||
});
|
||||
LOG ("edgeBounds: " << edgeBase-allBoundEdges);
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "boundaries link list:" << std::endl;
|
||||
for (int i = 0; i < edgeCounts.size (); ++i)
|
||||
printEdges (std::cout, edgeBounds[i], size, edgeCounts [i]) << std::endl;
|
||||
#endif
|
||||
unsigned int rangeIdx = 0;
|
||||
DimImg maxC = 0;
|
||||
utils::callOnSortedSets<DimImg, WeightT> (edgeCounts,
|
||||
[&edgeBounds] (const DimImg &vectId, const DimImg &itemId) {
|
||||
return edgeBounds [vectId][itemId].weight;
|
||||
},
|
||||
weightFunct.isWeightInf,
|
||||
[this, &tree, &edgeBounds, &topC, &maxC, &rangeIdx, &tileCount, &compBases, &compBase, &compTops, &size, &weightFunct] (const DimImg &vectId, const DimImg &itemId) {
|
||||
Edge<WeightT> *edge = &edgeBounds [vectId][itemId];
|
||||
if (topC == NULL || *topC >= maxC)
|
||||
for ( ; rangeIdx < tileCount; ++rangeIdx) {
|
||||
maxC = rangeIdx == tileCount-1 ? tree.getLeafCount() : compBases[rangeIdx+1];
|
||||
if (compTops[rangeIdx] < maxC) {
|
||||
compBase = compTops[rangeIdx];
|
||||
compBases.push_back (compBase);
|
||||
compTops.push_back (compBase);
|
||||
topC = &compTops[compTops.size ()-1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
connectLeaf (point2idx (size, edge->points[0]), point2idx (size, edge->points[1]), edge->weight, *topC, weightFunct);
|
||||
});
|
||||
}
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "link tiles" << std::endl;
|
||||
//printTree (size, true);
|
||||
#endif
|
||||
|
||||
DimImg maxUsed = std::max(compTops[tileCount-1], topC != NULL ? *topC : 0);
|
||||
std::fill_n (newCompIdx, maxUsed, DimImg_MAX);
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "reuse parent" << std::endl;
|
||||
//printNewCompIdx (size);
|
||||
#endif
|
||||
compCount = updateNewIdx (compBases, compTops, weightFunct);
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "newIndex" << std::endl;
|
||||
//printNewCompIdx (size);
|
||||
#endif
|
||||
compress (graphWalker, Rect (Point(), size), 0, maxUsed, weightFunct);
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "compressesed" << std::endl;
|
||||
//printNewCompIdx (size);
|
||||
//printTree (size, true);
|
||||
#endif
|
||||
|
||||
newCompIdx = NULL;
|
||||
parRnk.free ();
|
||||
|
||||
tree.setNodeCount(tree.getLeafCount() + compCount);
|
||||
LOG ("nodeCount:" << tree.getNodeCount());
|
||||
DimEdge root = compCount-1;
|
||||
compParents[root] = root;
|
||||
|
||||
buildChildren();
|
||||
|
||||
//createAttributsProfile (weightFunct);
|
||||
#ifdef SMART_LOG
|
||||
std::cout << "countRec children" << std::endl;
|
||||
//printMap (std::cout, childCount, size) << std::endl;
|
||||
Size doubleSize (size.width, 2*size.height);
|
||||
//printMap (std::cout, children, doubleSize) << std::endl;
|
||||
std::cout << "leafAP" << std::endl;
|
||||
//printMap (std::cout, ((const WeightT *) leafAP), doubleSize) << std::endl;
|
||||
#endif
|
||||
|
||||
delete[] compWeights;
|
||||
}
|
||||
|
||||
|
||||
// ========================================
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::buildTree(Edge<WeightT> *edges, const GraphWalker &graphWalker, const WeightFunct &weightFunct,
|
||||
const Rect &tile, DimImg &topParent, const bool &countingSortFlag) {
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("DapTree::buildTree", " tile:" << tile << " topParent:" << topParent << " counting:" << countingSortFlag);
|
||||
#endif
|
||||
DimEdge edgeCount = (sizeof (WeightT) < 3 || countingSortFlag) ?
|
||||
graphWalker.getCountingSortedEdges<WeightT, WeightFunct> (tile, Surface, edges, weightFunct) :
|
||||
graphWalker.getSortedEdges (tile, Surface, edges, weightFunct);
|
||||
|
||||
const Size &size = graphWalker.size;
|
||||
for (DimEdge edgeIdx = 0; edgeIdx < edgeCount; ++edgeIdx) {
|
||||
Edge<WeightT> &curEdge = edges[edgeIdx];
|
||||
DimImg la = point2idx (size, curEdge.points[0]);
|
||||
DimImg lb = point2idx (size, curEdge.points[1]);
|
||||
DimImg ra = parRnk.findUpdateParent (la);
|
||||
DimImg rb = parRnk.findUpdateParent (lb);
|
||||
#ifdef SMART_LOG
|
||||
LOG (" w:" << curEdge.weight << " la:" << la << " lb:" << lb << " ra:" << ra << " rb:" << rb);
|
||||
#endif
|
||||
if (ra == rb)
|
||||
continue;
|
||||
WeightT wa = leafParents[ra] != DimImg_MAX ? compWeights [leafParents[ra]] : weightFunct.getWeight (ra);
|
||||
WeightT wb = leafParents[rb] != DimImg_MAX ? compWeights [leafParents[rb]] : weightFunct.getWeight (rb);
|
||||
if (weightFunct.isWeightInf (wa, wb))
|
||||
std::swap (ra, rb);
|
||||
DimImg newLead = parRnk.linkParent (ra, rb, wa == wb, la, lb);
|
||||
// ALPHA et TOS: ef.get (leadPixel) = curEdge.weight pour MAX et? pour MIN
|
||||
DimImg parent = createComp (newLead, curEdge.weight, topParent, (DimNodeId) parRnk.getCount (newLead));
|
||||
#ifdef SMART_LOG
|
||||
LOG (" newLead:" << newLead << " p:" << parent << " c:" << parRnk.getCount (newLead));
|
||||
#endif
|
||||
if (ra != newLead)
|
||||
linkParent (ra, parent);
|
||||
if (rb != newLead)
|
||||
linkParent (rb, parent);
|
||||
}
|
||||
#ifdef SMART_LOG
|
||||
LOG ("topParent:" << topParent);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ========================================
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::connectLeaf (Tree &tree, DimImg a, DimImg b, const WeightT &weight, DimImg &parCount, const WeightFunct &weightFunct) {
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("DapTree::connectLeaf", "a:" << a << " b:" << b << " weight:" << weight);
|
||||
#endif
|
||||
BOOST_ASSERT (a < tree.getLeafCount());
|
||||
BOOST_ASSERT (b < tree.getLeafCount());
|
||||
BOOST_ASSERT (leafParents[a] < tree.getLeafCount());
|
||||
BOOST_ASSERT (leafParents[a] < tree.getLeafCount());
|
||||
// XXX si mauvaise bordure il peu ne pas y avoir de parent pour A ou B
|
||||
DimImg parA = findTopComp (leafParents[a], weightFunct);
|
||||
DimImg parB = findTopComp (leafParents[b], weightFunct);
|
||||
BOOST_ASSERT (parA < tree.getLeafCount());
|
||||
BOOST_ASSERT (parB < tree.getLeafCount());
|
||||
if (parA == parB)
|
||||
return;
|
||||
if (weightFunct.isWeightInf (compWeights[parA], compWeights[parB])) {
|
||||
std::swap(a, b);
|
||||
std::swap(parA, parB);
|
||||
}
|
||||
if (weightFunct.isWeightInf (weight, compWeights[parB])) {
|
||||
// 1
|
||||
BOOST_ASSERT (weightFunct.isWeightInf (weight, compWeights[parA]));
|
||||
--childCountRec[parA];
|
||||
--childCountRec[parB];
|
||||
#ifdef SMART_LOG
|
||||
LOG ("connect leaf a:" << a << " b:" << b << " np:" << parCount << " (2)");
|
||||
#endif
|
||||
DimImg newParent = leafParents[b] = leafParents[a] = parCount++;
|
||||
compWeights[newParent] = weight;
|
||||
childCountRec[newParent] = 2;
|
||||
connectComp (newParent, parA, parB, weightFunct);
|
||||
return;
|
||||
}
|
||||
if (weightFunct.isWeightInf (weight, compWeights[parA])) {
|
||||
// 2
|
||||
--childCountRec [parA];
|
||||
parB = findTopComp (parB, weight, weightFunct);
|
||||
BOOST_ASSERT (parB < tree.getLeafCount());
|
||||
if (weight == compWeights[parB]) {
|
||||
// 2a
|
||||
++childCountRec[parB];
|
||||
leafParents[a] = parB;
|
||||
#ifdef SMART_LOG
|
||||
LOG ("connect leaf a:" << a << " p:" << parB << " (" << childCountRec[parB] << ")");
|
||||
#endif
|
||||
connectComp (parA, parB, weightFunct);
|
||||
return;
|
||||
}
|
||||
// 2b compWeights[parB] < weight
|
||||
BOOST_ASSERT (weightFunct.isWeightInf (compWeights[parB], weight));
|
||||
DimImg grandParB = findTopComp (compParents[parB], weightFunct);
|
||||
--childCountRec [grandParB];
|
||||
#ifdef SMART_LOG
|
||||
LOG ("connect leaf a:" << a << " pb:" << parB << " np:" << parCount << " (2)");
|
||||
#endif
|
||||
DimImg newParent = leafParents[a] = compParents[parB] = parCount++;
|
||||
compWeights[newParent] = weight;
|
||||
childCountRec[newParent] = 2;
|
||||
connectComp (newParent, grandParB, parA, weightFunct);
|
||||
return;
|
||||
}
|
||||
parA = findTopComp (parA, weight, weightFunct);
|
||||
parB = findTopComp (parB, weight, weightFunct);
|
||||
BOOST_ASSERT (parA < tree.getLeafCount());
|
||||
BOOST_ASSERT (parB < tree.getLeafCount());
|
||||
if (weightFunct.isWeightInf (compWeights[parA], compWeights[parB]))
|
||||
std::swap(parA, parB);
|
||||
if (weightFunct.isWeightInf (compWeights[parA], weight)) {
|
||||
// 3
|
||||
BOOST_ASSERT (!weightFunct.isWeightInf (weight, compWeights[parA]));
|
||||
//BOOST_ASSERT (compParents[parA] < leafCount); // XXX pas sur !!!
|
||||
//BOOST_ASSERT (compParents[parB] < leafCount); // XXX pas sur !!!
|
||||
DimImg grandParA = findTopComp (compParents[parA], weightFunct);
|
||||
DimImg grandParB = findTopComp (compParents[parB], weightFunct);
|
||||
if (grandParA != DimImg_MAX)
|
||||
--childCountRec [grandParA];
|
||||
if (grandParB != DimImg_MAX)
|
||||
--childCountRec [grandParB];
|
||||
#ifdef SMART_LOG
|
||||
LOG ("connect leaf pa:" << parA << " pb:" << parB << " np:" << parCount << " (2)");
|
||||
#endif
|
||||
DimImg newParent = compParents[parA] = compParents[parB] = parCount++;
|
||||
compWeights[newParent] = weight;
|
||||
childCountRec[newParent] = 2;
|
||||
connectComp (newParent, grandParA, grandParB, weightFunct);
|
||||
return;
|
||||
}
|
||||
// 4
|
||||
connectComp (parA, parB, weightFunct);
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::connectComp (DimImg newComp, DimImg topA, DimImg topB, const WeightFunct &weightFunct) {
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("DapTree::connectComp", "newComp:" << newComp << " topA:" << topA << " topB:" << topB);
|
||||
#endif
|
||||
if (topB == DimImg_MAX)
|
||||
std::swap(topA, topB);
|
||||
BOOST_ASSERT (topB != DimImg_MAX);
|
||||
if (topA != DimImg_MAX && weightFunct.isWeightInf (compWeights[topA], compWeights[topB]))
|
||||
std::swap(topA, topB);
|
||||
BOOST_ASSERT (findTopComp (topB, weightFunct) == topB);
|
||||
compParents[newComp] = topB;
|
||||
++childCountRec[topB];
|
||||
#ifdef SMART_LOG
|
||||
LOG ("connect comp nc:" << newComp << " tb:" << topB << " (" << childCountRec[topB] << ")");
|
||||
#endif
|
||||
connectComp (topA, topB, weightFunct);
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::connectComp (DimImg topA, DimImg topB, const WeightFunct &weightFunct) {
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("DapTree::connectComp", "topA:" << topA << " topB:" << topB);
|
||||
#endif
|
||||
for (;;) {
|
||||
if (topA == DimImg_MAX || topB == DimImg_MAX)
|
||||
return;
|
||||
BOOST_ASSERT (findTopComp (topA, weightFunct) == topA);
|
||||
BOOST_ASSERT (findTopComp (topB, weightFunct) == topB);
|
||||
if (weightFunct.isWeightInf (compWeights[topA], compWeights[topB]))
|
||||
std::swap(topA, topB);
|
||||
topB = findTopComp (topB, compWeights[topA], weightFunct);
|
||||
if (topA == topB)
|
||||
return;
|
||||
if (compWeights[topA] == compWeights[topB]) {
|
||||
if (childCountRec[topA] < childCountRec[topB])
|
||||
std::swap (topA, topB);
|
||||
DimImg parB = findTopComp (compParents[topB], weightFunct);
|
||||
if (parB != DimImg_MAX)
|
||||
--childCountRec[parB];
|
||||
childCountRec [topA] += childCountRec[topB];
|
||||
childCountRec[topB] = 0;
|
||||
compParents[topB] = topA;
|
||||
#ifdef SMART_LOG
|
||||
LOG ("connect comp topB:" << topB << " topA:" << topA << " (" << childCountRec [topA] << ")");
|
||||
#endif
|
||||
topB = topA;
|
||||
topA = findTopComp (parB, compWeights[topA], weightFunct);
|
||||
continue;
|
||||
}
|
||||
DimImg parB = findTopComp (compParents[topB], weightFunct);
|
||||
++childCountRec[topA];
|
||||
compParents[topB] = topA;
|
||||
#ifdef SMART_LOG
|
||||
LOG ("connect comp topB:" << topB << " topA:" << topA << " (" << childCountRec [topA] << ")");
|
||||
#endif
|
||||
if (parB == DimImg_MAX)
|
||||
return;
|
||||
--childCountRec[parB];
|
||||
topB = findTopComp (topA, compWeights[parB], weightFunct);
|
||||
topA = parB;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::updateNewIdx (Tree &tree, const DimImg curComp, DimImg &compCount) {
|
||||
if (newCompIdx[curComp] != DimImg_MAX)
|
||||
// top already set
|
||||
return;
|
||||
const DimImg &top = findCompMultiChild (curComp);
|
||||
if (curComp != top) {
|
||||
// 0 => merge || no more child
|
||||
// 1 => unnecessary node
|
||||
BOOST_ASSERT (curComp != DimImg_MAX);
|
||||
DimImg newTopIdx = newCompIdx[top];
|
||||
if (newTopIdx == DimImg_MAX) {
|
||||
newTopIdx = newCompIdx[top] = compCount++;
|
||||
#ifdef SMART_LOG
|
||||
if (top == DimImg_MAX)
|
||||
// XXX arbres non-connexe ?
|
||||
std::cerr << "coucou top: " << curComp << std::endl;
|
||||
else if (compParents[top] == tree.getLeafCount())
|
||||
// XXX arbres non-connexe ?
|
||||
std::cerr << "coucou ptop-top: " << curComp << std::endl;
|
||||
else if (compParents[top] == DimImg_MAX)
|
||||
// XXX arbres non-connexe ?
|
||||
std::cerr << "coucou ptop-max: " << curComp << std::endl;
|
||||
#endif
|
||||
}
|
||||
const DimNodeId &newTopChildCountRec = childCountRec[top];
|
||||
const DimImg &newTopCompParent = compParents[top];
|
||||
const WeightT &newTopWeight = compWeights[top]; // only in case of unnecessary comp
|
||||
for (DimImg sibling = curComp; sibling != top; ) {
|
||||
DimImg nextSibling = compParents[sibling];
|
||||
newCompIdx[sibling] = newTopIdx;
|
||||
childCountRec[sibling] = newTopChildCountRec;
|
||||
compParents[sibling] = newTopCompParent;
|
||||
// only in case of unnecessary comp
|
||||
compWeights[sibling] = newTopWeight;
|
||||
sibling = nextSibling;
|
||||
}
|
||||
return;
|
||||
}
|
||||
newCompIdx[curComp] = compCount++;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::compress (const GraphWalker &graphWalker, const Rect &tile,
|
||||
const DimImg &compBase, const DimImg &compTop,
|
||||
const WeightFunct &weightFunct) {
|
||||
// XXX compress n'est plus utilisé que pour la fin
|
||||
// XXX donc virer l'argument tile et faire dealThreadRange pour la réindexation A et B mais pas C
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("DapTree::compress", "compBase:" << compBase << " compTop:" << compTop);
|
||||
#endif
|
||||
// XXX dealThreadRange if all (A)
|
||||
graphWalker.forEachVertexIdx (tile, [this] (const DimImg &leaf){
|
||||
//LOG ("leaf:" << leaf << " curPar:" << leafParents[leaf] << " newPar:" << newCompIdx[leafParents[leaf]]);
|
||||
DimImg old = leafParents[leaf];
|
||||
if (old != DimImg_MAX)
|
||||
leafParents[leaf] = newCompIdx[old];
|
||||
});
|
||||
// XXX dealThreadRange if all (B)
|
||||
for (DimImg curComp = compBase; curComp < compTop; ++curComp) {
|
||||
if (compParents[curComp] == DimImg_MAX)
|
||||
continue;
|
||||
compParents[curComp] = newCompIdx[compParents[curComp]];
|
||||
}
|
||||
// XXX (C)
|
||||
for (DimImg curComp = compBase; curComp < compTop; ) {
|
||||
DimImg newIdxComp = newCompIdx[curComp];
|
||||
if (newIdxComp == curComp || newIdxComp == DimImg_MAX || newCompIdx[newIdxComp] == newIdxComp) {
|
||||
++curComp;
|
||||
continue;
|
||||
}
|
||||
#ifdef SMART_LOG
|
||||
LOG ("comp curComp:" << curComp << " newIdxComp:" << newIdxComp);
|
||||
#endif
|
||||
std::swap(compParents[curComp], compParents[newIdxComp]);
|
||||
std::swap(compWeights[curComp], compWeights[newIdxComp]);
|
||||
std::swap(childCountRec[curComp], childCountRec[newIdxComp]);
|
||||
std::swap(newCompIdx[curComp], newCompIdx[newIdxComp]);
|
||||
}
|
||||
// XXX YYY curComp ? compTop ?
|
||||
}
|
||||
|
||||
// ========================================
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline DimImg
|
||||
DAPTreeBuilder<WeightT>::findTopComp (Tree &tree, const DimImg &comp, const WeightFunct &weightFunct) {
|
||||
if (comp == DimImg_MAX)
|
||||
return DimImg_MAX;
|
||||
DimImg result = findTopComp (comp, compWeights[comp], weightFunct);
|
||||
BOOST_ASSERT (result < tree.getLeafCount());
|
||||
// XXX pas pour TOS ! BOOST_ASSERT (compWeights[result] == compWeights[comp]);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline DimImg
|
||||
DAPTreeBuilder<WeightT>::findTopComp (DimImg comp, const WeightT &weight, const WeightFunct &weightFunct) {
|
||||
DimImg last = comp;
|
||||
for (;;) {
|
||||
if (comp == DimImg_MAX)
|
||||
return last;
|
||||
if (weightFunct.isWeightInf (weight, compWeights [comp]))
|
||||
return last;
|
||||
last = comp;
|
||||
comp = compParents[comp];
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
inline DimImg
|
||||
DAPTreeBuilder<WeightT>::findCompMultiChild (DimImg comp) {
|
||||
BOOST_ASSERT (comp != DimImg_MAX);
|
||||
for (;;) {
|
||||
if (newCompIdx [comp] != DimImg_MAX)
|
||||
return comp;
|
||||
const DimImg &parent = compParents[comp];
|
||||
if (parent == DimImg_MAX)
|
||||
return comp;
|
||||
if (childCountRec[comp] > 1 && compWeights[comp] != compWeights[parent])
|
||||
return comp;
|
||||
comp = parent;
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
template<typename WeightT>
|
||||
inline DimImg
|
||||
DAPTreeBuilder<WeightT>::createComp (Tree &tree, const DimImg &leadPixel, const WeightT &weight, DimImg &compTop, const DimNodeId &childCount) {
|
||||
BOOST_ASSERT (leadPixel < tree.getLeafCount());
|
||||
BOOST_ASSERT (compTop < tree.getLeafCount());
|
||||
DimImg newParent = leafParents[leadPixel];
|
||||
if (newParent == DimImg_MAX) {
|
||||
newParent = leafParents [leadPixel] = compTop++;
|
||||
compWeights[newParent] = weight;
|
||||
}
|
||||
childCountRec[newParent] = childCount;
|
||||
return newParent;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::linkParent (Tree &tree, const DimImg &pixel, const DimImg &parent) {
|
||||
BOOST_ASSERT (pixel < tree.getLeafCount());
|
||||
BOOST_ASSERT (parent < tree.getLeafCount());
|
||||
//BOOST_ASSERT (parent < compTop);
|
||||
if (leafParents [pixel] == parent)
|
||||
return;
|
||||
if (leafParents [pixel] == DimImg_MAX) {
|
||||
leafParents [pixel] = parent;
|
||||
return;
|
||||
}
|
||||
DimImg leadPixelParent = leafParents [pixel];
|
||||
if (compParents [leadPixelParent] == parent)
|
||||
return;
|
||||
BOOST_ASSERT (compParents [leadPixelParent] == DimImg_MAX);
|
||||
compParents [leadPixelParent] = parent;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::buildChildren(Tree &tree) {
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("DapTree::buildChildren", "");
|
||||
#endif
|
||||
BOOST_ASSERT (childCount[0] == 0);
|
||||
BOOST_ASSERT (childCount[1] == 0);
|
||||
|
||||
DimImg compCount = tree.getNodeCount() - tree.getLeafCount();
|
||||
std::partial_sum(childCountRec, childCountRec+compCount, childCountRec);
|
||||
|
||||
// set
|
||||
DimNodeId *childGetOrder = childCount+1;
|
||||
for (DimNodeId i = 0; i < tree.getNodeCount()-1; ++i) {
|
||||
if (leafParents[i] == DimImg_MAX)
|
||||
continue;
|
||||
BOOST_ASSERT (leafParents[i] < compCount);
|
||||
children[childGetOrder[leafParents[i]]++] = i;
|
||||
}
|
||||
BOOST_ASSERT (childCount[0] == 0);
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename WeightT>
|
||||
template<typename WeightFunct>
|
||||
inline void
|
||||
DAPTreeBuilder<WeightT>::initWeights (Tree &tree, const GraphWalker &graphWalker, const WeightFunct &weightFunct) {
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("DapTree::initCompWeights", "leafCount:" << tree.getLeafCount());
|
||||
#endif
|
||||
// graphWalker.forEachVertexIdx ([this, &weightFunct] (const DimImg &compIdx){
|
||||
// mapWeights[compIdx] = weightFunct.getWeight (compIdx);
|
||||
// });
|
||||
std::fill_n (compWeights, tree.getLeafCount(), 0);
|
||||
}
|
||||
|
||||
|
||||
} // otb
|
88
include/DAPTree/GraphWalker.hpp
Normal file
88
include/DAPTree/GraphWalker.hpp
Normal file
@ -0,0 +1,88 @@
|
||||
#ifndef GRAPHWALKER_HPP
|
||||
#define GRAPHWALKER_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
#include "debug.hpp"
|
||||
#include "baseDef.hpp"
|
||||
#include "baseDAPTree.hpp"
|
||||
#include "Border.hpp"
|
||||
|
||||
#ifdef GRAPHWALKER_NO_BORDER
|
||||
#define GRAPHWALKER_CALL_LAMBDA_IDX(idx, count, lambda) lambda, count++
|
||||
#define GRAPHWALKER_CALL_LAMBDA_PTS(p1, p2, count, lambda) lambda, count++
|
||||
#else
|
||||
#define GRAPHWALKER_CALL_LAMBDA_IDX(idx, count, lambda) if (!border.isBorder (idx)) lambda, count++
|
||||
#define GRAPHWALKER_CALL_LAMBDA_PTS(p1, p2, count, lambda) if (!(border.isBorder (p1) || border.isBorder (p2))) lambda, count++
|
||||
#endif
|
||||
|
||||
namespace otb {
|
||||
|
||||
/**
|
||||
* GraphWalker
|
||||
*/
|
||||
|
||||
class GraphWalker {
|
||||
public:
|
||||
|
||||
GraphWalker (const Size &size, const Border &border, const Connectivity &connectivity = Connectivity::C4)
|
||||
: size (size), border (border), connectivity (connectivity) {
|
||||
BOOST_ASSERT (size.width >= DimImg (0));
|
||||
BOOST_ASSERT (size.height >= DimImg (0));
|
||||
}
|
||||
|
||||
DimImg vertexMaxCount() const;
|
||||
DimImg vertexMaxCount(const Size &tileSize) const;
|
||||
DimEdge edgeMaxCount() const;
|
||||
DimEdge edgeMaxCount(const Size &tileSize) const;
|
||||
DimEdge edgeBoundaryMaxCount(const DimSideImg &side) const;
|
||||
|
||||
void setTiles(const unsigned int &coreCount, const Rect &tile,
|
||||
std::vector<Rect> &tiles, std::vector<Rect> &boundaries, std::vector<bool> &verticalBoundaries) const;
|
||||
|
||||
template<typename Funct>
|
||||
DimImg
|
||||
forEachVertexIdx(const Funct &lambda /*lambda (idx)*/) const;
|
||||
template<typename Funct>
|
||||
DimImg
|
||||
forEachVertexPt(const Funct &lambda /*lambda (p)*/) const;
|
||||
template<typename Funct>
|
||||
DimImg
|
||||
forEachVertexIdx(const Rect &rect, const Funct &lambda /*lambda (idx)*/) const;
|
||||
template<typename Funct>
|
||||
DimImg
|
||||
forEachVertexPt(const Rect &rect, const Funct &lambda /*lambda (p)*/) const;
|
||||
|
||||
template<typename Funct>
|
||||
DimEdge
|
||||
forEachEdgePt(const Rect &rect, TileItem tileItem, const Funct &lambda /*lambda (p0, p1)*/) const;
|
||||
|
||||
template <typename WeightT, typename EdgeWeightFunction>
|
||||
WeightT
|
||||
getMedian(const EdgeWeightFunction &ef /*ef.getValue (idx)*/) const;
|
||||
|
||||
template<typename WeightT, typename EdgeWeightFunction>
|
||||
DimEdge
|
||||
getEdges(const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1)*/) const;
|
||||
template<typename WeightT, typename EdgeWeightFunction>
|
||||
DimEdge
|
||||
getSortedEdges(const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1) ef.sort ()*/) const;
|
||||
template<typename WeightT, typename EdgeWeightFunction>
|
||||
DimEdge
|
||||
getCountingSortedEdges(const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1)*/) const;
|
||||
|
||||
public:
|
||||
const Size size;
|
||||
const Border &border;
|
||||
const Connectivity connectivity;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // GRAPHWALKER_HPP
|
78
include/DAPTree/ParRnk.hpp
Normal file
78
include/DAPTree/ParRnk.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef PARRNK_HPP
|
||||
#define PARRNK_HPP
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <memory>
|
||||
|
||||
#include "debug.hpp"
|
||||
#include "baseDef.hpp"
|
||||
#include "baseDAPTree.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
/**
|
||||
* ParRnk
|
||||
*/
|
||||
|
||||
class ParRnk {
|
||||
public:
|
||||
ParRnk () : size (0), count (NULL), parent (NULL) {}
|
||||
~ParRnk () { free (); }
|
||||
|
||||
/*! Remet à 0 et redéfinit la taille des tableaux */
|
||||
void book(DimImg vertexCount);
|
||||
|
||||
/*! Remplit count de 1 et parent de DimImg_MAX */
|
||||
void reset();
|
||||
|
||||
/*! Libère la mémoire allouée par les tableaux et met size à 0 */
|
||||
void free();
|
||||
|
||||
/*! Accesseur sur un élément de count */
|
||||
DimImg getCount(const DimImg &r) const { return count [r]; }
|
||||
|
||||
/*! Retourne le parent de a */
|
||||
DimImg findParent(const DimImg &a) const { return find (a); }
|
||||
|
||||
/*! Met à jour les parents de a */
|
||||
DimImg findUpdateParent(const DimImg &a) {
|
||||
DimImg r = find (a);
|
||||
link (a, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*! Redéfinit le père de a et b comme étant le père le plus logique entre maxLevel et minLevel.
|
||||
* Si maxLevel et minLevel ont les mêmes niveaux, le nouveau père sera celui ayant le plus de fils.
|
||||
* Le nouveau père de minLevel est maxLevel.
|
||||
*/
|
||||
DimImg linkParent(DimImg maxLevel, DimImg minLevel, const bool &same,
|
||||
const DimImg &a, const DimImg &b);
|
||||
|
||||
const DimImg *getCount() const { return count; }
|
||||
DimImg *getParent() const { return parent; }
|
||||
|
||||
private:
|
||||
/*! Cherche le parent du pixel a, Si a n'en a pas, cela retourne a */
|
||||
DimImg find(DimImg a) const;
|
||||
|
||||
/*! Rédéfinit les parents : a et tous les parents de a ont pour parent r */
|
||||
void link(DimImg a, const DimImg &r);
|
||||
|
||||
private:
|
||||
|
||||
/*! Taille de l'image (donc des tableaux count et parent) */
|
||||
DimImg size;
|
||||
|
||||
/*! Compte le nombre de fils, différence avec Tarjan qui possède simplement un compteur */
|
||||
DimImg *count;
|
||||
|
||||
/*! Tableau des parents, chaque case contient une référence vers son parent */
|
||||
DimImg *parent;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // PARRNK_HPP
|
143
include/DAPTree/Weight.hpp
Normal file
143
include/DAPTree/Weight.hpp
Normal file
@ -0,0 +1,143 @@
|
||||
#ifndef WEIGHT_HPP
|
||||
#define WEIGHT_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "baseDef.hpp"
|
||||
#include "baseDAPTree.hpp"
|
||||
#include "GraphWalker.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
/*! Structure définissant la base d'un poids entre les pixels */
|
||||
template <typename PixelT> struct WeightBase {
|
||||
protected:
|
||||
const PixelT *pixels;
|
||||
const Size size;
|
||||
DimNodeId pointIdx (const Point &p) const { return pointToId (size, p); }
|
||||
PixelT halfPixel, maxPixel;
|
||||
public:
|
||||
const Size &getSize () const { return size; }
|
||||
const PixelT &getValue (const DimImg &idx) const { return pixels[idx]; }
|
||||
const PixelT &getValue (const Point &p) const { return getValue (pointIdx (p)); }
|
||||
bool getDecr () const { return false; }
|
||||
const PixelT &getMaxPixel () const { return maxPixel; }
|
||||
const PixelT &getHalfPixel () const { return halfPixel; }
|
||||
|
||||
PixelT *allocAP (const DimNodeId &nodeCapacity) const { return new PixelT [nodeCapacity]; }
|
||||
|
||||
WeightBase (const PixelT *pixels, const Size &size) : pixels (pixels), size (size) {
|
||||
maxPixel = std::numeric_limits<PixelT>::max ();
|
||||
// only if unsigned
|
||||
halfPixel = maxPixel / 2;
|
||||
if (typeid (PixelT) != typeid (float))
|
||||
halfPixel++;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename PixelT, typename WeightT> struct WeightBase2 : public WeightBase<PixelT> {
|
||||
typedef WeightBase<PixelT> WB;
|
||||
|
||||
WeightBase2 (const PixelT *pixels, const Size &size)
|
||||
: WB (pixels, size) {}
|
||||
|
||||
static bool isWeightInf (const WeightT &a, const WeightT &b) { return a < b; }
|
||||
static bool isEdgeInf (const Edge<WeightT> &a, const Edge<WeightT> &b) { return isWeightInf (a.weight, b.weight); }
|
||||
static void sort (Edge<WeightT> *edges, DimEdge count) { std::sort(edges, edges+count, isEdgeInf); }
|
||||
|
||||
void fillLeafAP (void *leafAP, const DimNodeId &leafCount) const { std::memcpy((PixelT *)leafAP, WB::pixels, leafCount*sizeof (PixelT)); }
|
||||
void fillCompAP (void *leafAP, const WeightT *compWeights, const DimNodeId &leafCount, const DimNodeId &compCount) const {
|
||||
std::memcpy(&((PixelT *)leafAP)[leafCount], compWeights, compCount*sizeof (PixelT));
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================
|
||||
/*! Structure intégrant la façon dont est géré un poids pour un MinTree */
|
||||
template <typename PixelT, typename WeightT> struct MinWeight : public WeightBase2<PixelT, WeightT> {
|
||||
typedef WeightBase2<PixelT, WeightT> WB;
|
||||
|
||||
bool getDecr () const { return true; }
|
||||
static bool isWeightInf (const WeightT &a, const WeightT &b) { return a > b; }
|
||||
static bool isEdgeInf (const Edge<WeightT> &a, const Edge<WeightT> &b) { return isWeightInf (a.weight, b.weight); }
|
||||
static void sort (Edge<WeightT> *edges, DimEdge count) { std::sort (edges, edges+count, isEdgeInf); }
|
||||
|
||||
MinWeight (const PixelT *pixels, const Size &size)
|
||||
: WB (pixels, size) {}
|
||||
|
||||
WeightT getWeight (const DimImg &idx) const { return WB::getValue (idx); }
|
||||
WeightT getWeight (const Point &a, const Point &b) const { return std::min (getWeight (WB::pointIdx (a)),
|
||||
getWeight (WB::pointIdx (b))); }
|
||||
};
|
||||
|
||||
|
||||
// ========================================
|
||||
/*! Structure intégrant la façon dont est géré un poids pour un MaxTree */
|
||||
template <typename PixelT, typename WeightT> struct MaxWeight : public WeightBase2<PixelT, WeightT> {
|
||||
typedef WeightBase2<PixelT, WeightT> WB;
|
||||
|
||||
MaxWeight (const PixelT *pixels, const Size &size)
|
||||
: WB (pixels, size) {}
|
||||
|
||||
WeightT getWeight (const DimImg &idx) const { return WB::getValue (idx); }
|
||||
WeightT getWeight (const Point &a, const Point &b) const { return std::max (getWeight (WB::pointIdx (a)),
|
||||
getWeight (WB::pointIdx (b))); }
|
||||
};
|
||||
|
||||
|
||||
// ========================================
|
||||
/*! Structure intégrant la façon dont est géré un poids pour un TreeOfShape */
|
||||
template <typename PixelT, typename WeightT> struct MedianWeight : public WeightBase2<PixelT, WeightT> {
|
||||
typedef WeightBase2<PixelT, WeightT> WB;
|
||||
protected:
|
||||
PixelT median, thresholdPixel;
|
||||
WeightT thresholdWeight;
|
||||
|
||||
public:
|
||||
bool getDecr () const { return true; }
|
||||
static bool isWeightInf (const WeightT &a, const WeightT &b) { return a > b; }
|
||||
static bool isEdgeInf (const Edge<WeightT> &a, const Edge<WeightT> &b) { return isWeightInf (a.weight, b.weight); }
|
||||
static void sort (Edge<WeightT> *edges, DimEdge count) { std::sort (edges, edges+count, isEdgeInf); }
|
||||
|
||||
const PixelT &getMedian () const { return median; }
|
||||
const PixelT &getThresholdPixel () const { return thresholdPixel; }
|
||||
const WeightT &getThresholdWeight () const { return thresholdWeight; }
|
||||
|
||||
WeightT value2weight (const PixelT &val) const {
|
||||
if (median < WB::halfPixel) {
|
||||
if (val >= thresholdPixel)
|
||||
return val;
|
||||
return val < median ? (median-val)*2 - 1 : (val-median)*2;
|
||||
}
|
||||
if (val < thresholdPixel)
|
||||
return WB::maxPixel - val;
|
||||
return val < median ? (median-val)*2 - 1 : (val-median)*2;
|
||||
}
|
||||
PixelT weight2value (const WeightT &weight) const {
|
||||
if (median < WB::halfPixel) {
|
||||
if (weight >= thresholdWeight)
|
||||
return weight;
|
||||
return int (weight) % 2 ? median - 1 - weight/2 : median + weight/2;
|
||||
}
|
||||
if (weight > thresholdWeight)
|
||||
return WB::maxPixel - weight;
|
||||
return int (weight) % 2 ? median - weight/2 : median + weight/2;
|
||||
}
|
||||
|
||||
inline MedianWeight (const PixelT *pixels, const GraphWalker &graphWalker);
|
||||
|
||||
WeightT getWeight (const DimImg &idx) const { return value2weight (WB::getValue (idx)); }
|
||||
WeightT getWeight (const Point &a, const Point &b) const { return std::min (getWeight (WB::pointIdx (a)),
|
||||
getWeight (WB::pointIdx (b))); }
|
||||
//void fillLeafAP (void *leafAP, const DimImg &leafCount) const { memcpy ((PixelT *)leafAP, WB::pixels, leafCount*sizeof (PixelT)); }
|
||||
void fillCompAP (void *leafAP, const WeightT *compWeights, const DimImg &leafCount, const DimImg &compCount) const {
|
||||
PixelT *compAP = ((PixelT *)leafAP)+leafCount;
|
||||
for (DimImg compIdx = 0; compIdx < compCount; ++compIdx)
|
||||
compAP[compIdx] = weight2value (compWeights[compIdx]);
|
||||
}
|
||||
};
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // WEIGHT_HPP
|
116
include/DAPTree/baseDAPTree.hpp
Normal file
116
include/DAPTree/baseDAPTree.hpp
Normal file
@ -0,0 +1,116 @@
|
||||
#ifndef BASEDAPTREE_HPP
|
||||
#define BASEDAPTREE_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/assert.hpp>
|
||||
#include <climits>
|
||||
|
||||
#include "baseDef.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
/*! Nombre de voisins */
|
||||
typedef uint32_t DimEdge; // ~4*nbPixels (8-connectivity)
|
||||
|
||||
/*! Type de connectivité possible pour le voisinage */
|
||||
enum Connectivity { C4 = 0, C6P = 1, C6N = 2, C8 = C6P | C6N };
|
||||
|
||||
/*! Définit de quel type est la "sélection" */
|
||||
enum TileItem { Surface, Horizontal, Vertical };
|
||||
|
||||
/* Définit le type d'arbre à construire */
|
||||
enum TreeType { MIN, MAX, TOS, /*ALPHA*/};
|
||||
|
||||
/*! Compte le nombre de bits utilisés pour chaque nombre : bitCount[nombre] = nombre de bits*/
|
||||
extern int bitCount[];
|
||||
|
||||
enum treeType {
|
||||
minE,
|
||||
maxE,
|
||||
tosE,
|
||||
treeTypeCount
|
||||
};
|
||||
|
||||
/*! Définit les noms des connectivités (utile pour le debug) */
|
||||
extern std::string connectivityName[];
|
||||
|
||||
/*! Définit les noms des tileItem (utile pour le debug) */
|
||||
extern std::string tileItemName[];
|
||||
|
||||
/*! Définit les noms des arbres (utile pour le debug) */
|
||||
extern std::string treeName[];
|
||||
|
||||
/*!
|
||||
* Opérateur de flux sur les connectivités
|
||||
*/
|
||||
|
||||
inline std::ostream &operator << (std::ostream &out, const Connectivity &c) {
|
||||
BOOST_ASSERT (c >= 0 && c < 4);
|
||||
return out << connectivityName[c];
|
||||
}
|
||||
|
||||
/*!
|
||||
* Opérateur de flux sur les TileItem
|
||||
*/
|
||||
|
||||
inline std::ostream &operator << (std::ostream &out, const TileItem &t) {
|
||||
BOOST_ASSERT (t >= 0 && t < 3);
|
||||
return out << tileItemName[t];
|
||||
}
|
||||
|
||||
|
||||
template <typename WeightT> struct Edge {
|
||||
Point points[2];
|
||||
WeightT weight;
|
||||
};
|
||||
|
||||
/*! Effectue l'échange entre 2 Edge */
|
||||
template <typename WeightT>
|
||||
inline void swapEdge (Edge<WeightT> &a, Edge<WeightT> &b) {
|
||||
Edge<WeightT> c = a;
|
||||
a = b;
|
||||
b = c;
|
||||
}
|
||||
|
||||
/*! Opérateur de flux sur les voisins */
|
||||
template <typename WeightT>
|
||||
inline std::ostream &operator << (std::ostream &out, const Edge<WeightT> &edge) {
|
||||
return out << edge.points[0] << ":" << edge.points[1] << ":" << edge.weight;
|
||||
}
|
||||
template <typename WeightT>
|
||||
inline std::ostream &printEdge (std::ostream &out, const Edge<WeightT> &edge, const Size &size) {
|
||||
return out << edge.points[0] << ":" << edge.points[1] << ":" << edge.weight << ":"
|
||||
<< point2idx (size, edge.points[0]) << ":" << point2idx (size, edge.points[1]);
|
||||
}
|
||||
|
||||
/*! Affiche tous les voisins d'un ensemble */
|
||||
template <typename Edge>
|
||||
inline std::ostream &printEdges (std::ostream &out, const std::vector<Edge> &edges) {
|
||||
for (int i = 0; i < edges.size (); ++i)
|
||||
out << " " << edges [i];
|
||||
return out;
|
||||
}
|
||||
template <typename Edge>
|
||||
inline std::ostream &printEdges (std::ostream &out, const Edge edges[], const Size &size, const DimEdge edgesCount) {
|
||||
for (int i = 0; i < edgesCount; ++i)
|
||||
printEdge (out, edges[i], size) << std::endl;
|
||||
return out;
|
||||
}
|
||||
|
||||
/*! Affiche tous les voisins d'un ensembles à l'aide de leurs coordonnées */
|
||||
template <typename Edge>
|
||||
inline std::ostream &printEdges (std::ostream &out, const std::vector<Edge> &edges, const Size &size) {
|
||||
for (int i = 0; i < edges.size (); ++i)
|
||||
out << " [" << point2idx (size, edges [i].points[0])
|
||||
<< " " << point2idx (size, edges [i].points[1])
|
||||
<< " " << edges [i].weight << "]";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // BASEDAPTREE_HPP
|
20
include/DAPTree/sort.hpp
Normal file
20
include/DAPTree/sort.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef SORT_HPP
|
||||
#define SORT_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace otb {
|
||||
|
||||
template <typename T>
|
||||
inline std::vector<T> getRandReduce(std::vector<T> index, T reduceCount);
|
||||
|
||||
template <typename E, typename WeightT, typename DimImg, typename WeightFunct>
|
||||
inline DimImg mergeSort(E *dst, const std::vector<E *> &tab, const std::vector<DimImg> &tabSize, const WeightFunct &weightFunct);
|
||||
|
||||
// ========================================
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // SORT_HPP
|
73
include/ImageInterface.hpp
Normal file
73
include/ImageInterface.hpp
Normal file
@ -0,0 +1,73 @@
|
||||
#ifndef IMAGEINTERFACE_HPP
|
||||
#define IMAGEINTERFACE_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <gdal/gdal_priv.h>
|
||||
|
||||
#include "baseDef.hpp"
|
||||
#include "getType.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
/**
|
||||
* ImageInterface
|
||||
*/
|
||||
|
||||
template<typename PixelT>
|
||||
class ImageInterface {
|
||||
public:
|
||||
ImageInterface(const std::string &imageFilename) : filename(imageFilename), read(false) {}
|
||||
|
||||
~ImageInterface() { close(); if (pixels) delete[] pixels; pixels = nullptr; }
|
||||
|
||||
PixelT *getPixels() { return pixels; }
|
||||
|
||||
PixelT getValue(const DimImg &id) const { return pixels[id]; }
|
||||
PixelT getValue(const Point &point) const { return pixels[pointToId(size, point)]; }
|
||||
|
||||
const std::string &getFilename() const { return filename; }
|
||||
|
||||
DimImg getPixelsCount() const { return (DimImg)size.width * (DimImg)size.height; }
|
||||
|
||||
const Size &getSize() const { return size; }
|
||||
|
||||
bool isEmpty() const { return getPixelsCount() == 0; }
|
||||
|
||||
GDALDataType getDataType() const { return dataType; }
|
||||
|
||||
void readImage(const Point &cropOrig, const Size &cropSize);
|
||||
|
||||
void readImage() { readImage(Point(), size); }
|
||||
|
||||
void close();
|
||||
|
||||
const bool &isRead() const { return read; }
|
||||
|
||||
private:
|
||||
ImageInterface(const ImageInterface &o) = delete;
|
||||
ImageInterface& operator=(const ImageInterface&) = delete;
|
||||
|
||||
private:
|
||||
static uint32_t gdalCount;
|
||||
|
||||
std::string filename;
|
||||
|
||||
Size size;
|
||||
|
||||
GDALDataType dataType;
|
||||
|
||||
GDALDataset *gdalInputDataset;
|
||||
|
||||
PixelT* pixels;
|
||||
|
||||
bool read;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
#include "ImageInterface.tpp"
|
||||
|
||||
#endif // IMAGEINTERFACE_HPP
|
51
include/ImageInterface.tpp
Normal file
51
include/ImageInterface.tpp
Normal file
@ -0,0 +1,51 @@
|
||||
#include "ImageInterface.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace otb {
|
||||
|
||||
template<typename PixelT>
|
||||
uint32_t
|
||||
ImageInterface<PixelT>::gdalCount = 0;
|
||||
|
||||
template<typename PixelT>
|
||||
void
|
||||
ImageInterface<PixelT>::readImage(const Point &cropOrig, const Size &cropSize) {
|
||||
DEF_LOG("ImageInterface::readImage", "filename: " << filename);
|
||||
if (!gdalCount++)
|
||||
GDALAllRegister();
|
||||
|
||||
gdalInputDataset = (GDALDataset *) GDALOpen (filename.c_str(), GA_ReadOnly);
|
||||
|
||||
if (!gdalInputDataset) {
|
||||
dataType = GDT_Unknown;
|
||||
std::cerr << "GDALError: can't define dataset" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
size = Size (gdalInputDataset->GetRasterXSize(), gdalInputDataset->GetRasterYSize());
|
||||
LOG("size: " << size);
|
||||
pixels = new PixelT[getPixelsCount()];
|
||||
|
||||
LOG("bandsCount: " << gdalInputDataset->GetRasterCount());
|
||||
|
||||
GDALRasterBand &poBand = *gdalInputDataset->GetRasterBand(1);
|
||||
CPLErr err = poBand.RasterIO (GF_Read, cropOrig.x, cropOrig.y, cropSize.width, cropSize.height, pixels, cropSize.width, cropSize.height, toGDALType(getType((PixelT)0)), 0, 0);
|
||||
|
||||
if (err != CE_None)
|
||||
std::cerr << "GDALError: can't acces " << filename << std::endl;
|
||||
}
|
||||
|
||||
template<typename PixelT>
|
||||
void
|
||||
ImageInterface<PixelT>::close() {
|
||||
if (gdalInputDataset) {
|
||||
GDALClose(gdalInputDataset);
|
||||
gdalInputDataset = nullptr;
|
||||
if (!--gdalCount)
|
||||
GDALDestroyDriverManager();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // otb
|
35
include/QuadTree/QuadTreeBuilder.hpp
Normal file
35
include/QuadTree/QuadTreeBuilder.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#ifndef QUADTREEBUILDER_HPP
|
||||
#define QUADTREEBUILDER_HPP
|
||||
|
||||
#include "BuildTree.hpp"
|
||||
#include "baseDef.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
class QuadTreeBuilder : public BuildTree {
|
||||
public:
|
||||
|
||||
QuadTreeBuilder(const DimSideImg &w, const DimSideImg &h) : width(w),
|
||||
height(h)
|
||||
{}
|
||||
|
||||
virtual void
|
||||
buildTree(Tree &tree);
|
||||
|
||||
private:
|
||||
|
||||
DimImg
|
||||
getStepCount(const DimSideImg &x, const DimSideImg &y, const DimSideImg &w, const DimSideImg &h) const;
|
||||
|
||||
DimImg
|
||||
setParents(DimImg &parentId,
|
||||
const DimSideImg &x, const DimSideImg &y, const DimSideImg &w, const DimSideImg &h,
|
||||
const DimSideImg &imgW, const DimSideImg &imgH, DimImg level = 0) const;
|
||||
|
||||
private:
|
||||
DimSideImg width, height;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // QUADTREEBUILDER_HPP
|
119
include/Tree.hpp
Normal file
119
include/Tree.hpp
Normal file
@ -0,0 +1,119 @@
|
||||
#ifndef OTREE_HPP
|
||||
#define OTREE_HPP
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <numeric>
|
||||
|
||||
#include "baseDef.hpp"
|
||||
#include "debug.hpp"
|
||||
|
||||
|
||||
namespace otb {
|
||||
enum State {
|
||||
Void = 0,
|
||||
Initialized = 1,
|
||||
Constructed = 1 << 1
|
||||
};
|
||||
|
||||
class Tree {
|
||||
friend class BuildTree;
|
||||
|
||||
protected:
|
||||
|
||||
/*! Info about the picture */
|
||||
Size size;
|
||||
|
||||
/*! Number of pixels / leaf */
|
||||
DimImg leafCount, nodeCount;
|
||||
|
||||
/*! Pointers on the parents of each leafs / nodes */
|
||||
DimNodeId *leafParents, *compParents;
|
||||
|
||||
/*! Pointers on the children and count how many children a parents have */
|
||||
DimNodeId *children, *childCount;
|
||||
|
||||
DimNodeId *newCompIndex;
|
||||
|
||||
/*! State of the tree */
|
||||
State state;
|
||||
|
||||
/*! Reset the tree and allocate the memory according to the size defined */
|
||||
void init();
|
||||
|
||||
/*! Allocate the size according to the size previously defined */
|
||||
void book();
|
||||
|
||||
/*! Free all the memory and set all pointers to nullptr */
|
||||
void reset();
|
||||
|
||||
public:
|
||||
|
||||
// Constructors, destructor and resize method (does the same as the constructors)
|
||||
|
||||
Tree(const DimImg &leafCount, const DimSideImg &width, const DimSideImg &height);
|
||||
Tree(const DimSideImg &width, const DimSideImg &height);
|
||||
Tree(const DimImg &leafCount = 0);
|
||||
~Tree();
|
||||
|
||||
|
||||
void resize(const DimImg &newLeafCount, const DimSideImg &w, const DimSideImg &h);
|
||||
void resize(const DimImg &newLeafCount);
|
||||
void resize(const DimSideImg &w, const DimSideImg &h);
|
||||
|
||||
// Setter for nodeCount and size
|
||||
|
||||
void setNodeCount(const DimImg &newNodeCount) { nodeCount = newNodeCount; }
|
||||
void setSize(const Size &newSize) { size = newSize; }
|
||||
|
||||
// Getters for tree structure
|
||||
|
||||
DimNodeId getRoot() const { return nodeCount-1; }
|
||||
DimNodeId getAbsRoot() const { return nodeCount-1+leafCount; }
|
||||
DimNodeId getCompCount () const { return nodeCount-leafCount; } // XXX
|
||||
|
||||
DimNodeId getParent(const DimNodeId &idx) const { return leafParents[idx]; }
|
||||
DimNodeId getLeafParent(const DimNodeId &idx) const { return leafParents[idx]; }
|
||||
DimNodeId getCompParent(const DimNodeId &idx) const { return compParents[idx]; }
|
||||
|
||||
std::vector<DimNodeId> getChildren(const DimImg &idx) const;
|
||||
|
||||
DimNodeId getChildrenCount(const DimImg &idx) const { return childCount[idx]; }
|
||||
|
||||
DimSideImg getLeafCount() const { return leafCount; }
|
||||
|
||||
DimSideImg getNodeCount() const { return nodeCount; }
|
||||
|
||||
// Functions to apply to specific entities
|
||||
|
||||
template<typename FuncToApply>
|
||||
void forEachLeaf(const FuncToApply& f /* f(DimNodeId idx) */);
|
||||
|
||||
template<typename FuncToApply>
|
||||
void forEachComp(const FuncToApply& f /* f(DimNodeId idx) */);
|
||||
|
||||
template<typename FuncToApply>
|
||||
void forEachChild(const DimNodeId &idx, const FuncToApply& f /* f(DimNodeId idx) */);
|
||||
|
||||
// Get the tree state and the size
|
||||
|
||||
State getState() const { return state; }
|
||||
|
||||
Size getSize() const { return size; }
|
||||
|
||||
|
||||
#ifdef SMART_LOG
|
||||
// Print info about the tree
|
||||
|
||||
void printTree (const Size &size, const bool &rec);
|
||||
void printNewCompIndex (const Size &size);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
#endif // OTREE_HPP
|
67
include/TreeOfShapesGeraud/ToSBuilder.hpp
Normal file
67
include/TreeOfShapesGeraud/ToSBuilder.hpp
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef TOSBUILDER_HPP
|
||||
#define TOSBUILDER_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
|
||||
#include "BuildTree.hpp"
|
||||
#include "TreeOfShapesGeraud/ToSutils.hpp"
|
||||
|
||||
|
||||
namespace otb {
|
||||
|
||||
/**
|
||||
* TosBuilder
|
||||
*/
|
||||
|
||||
class ToSBuilder : public BuildTree {
|
||||
public:
|
||||
ToSBuilder(const std::string &fileName);
|
||||
|
||||
void
|
||||
buildTree(Tree &tree);
|
||||
|
||||
private:
|
||||
void
|
||||
interpolateImg(const cv::Mat &imgTrue, std::vector<std::vector<std::pair<uchar, uchar>>> &iimg) const;
|
||||
|
||||
void
|
||||
sortImgElemsToS(const std::vector <std::vector <std::pair<uchar, uchar>>> &iimg,
|
||||
std::vector<pxCoord> &order, cv::Mat &eimg) const;
|
||||
|
||||
void
|
||||
unInterpolateParent(std::vector<std::vector<pxCoord>> parentOld, const cv::Mat &ub,
|
||||
std::vector<std::vector <pxCoord>> &parentNew) const;
|
||||
|
||||
pxCoord
|
||||
specialPop(std::vector<std::vector<pxCoord>> &q, int &qElems, const uchar &lo, uchar &level) const;
|
||||
|
||||
void
|
||||
specialPush(std::vector<std::vector<pxCoord>> &q, int &qElems, const uchar &lo, const uchar &level,
|
||||
const pxCoord &coord, const std::pair<uchar, uchar> &bounds) const;
|
||||
|
||||
void
|
||||
canonizeTree(const std::vector<pxCoord> &sorted, std::vector<std::vector<pxCoord>> &parent, const cv::Mat &img) const;
|
||||
|
||||
pxCoord
|
||||
findRoot(const pxCoord &px, std::vector<std::vector<pxCoord>> &zpar) const;
|
||||
|
||||
void
|
||||
treeCore(const std::vector<pxCoord> &sorted, pxType curType, std::vector<std::vector<pxCoord>> &parent) const;
|
||||
|
||||
bool
|
||||
isKhalimskyOriginalPixel(const pxCoord &kpx, const int oX, const int oY) const;
|
||||
|
||||
|
||||
private:
|
||||
std::string imagePath;
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // TOSBUILDER_HPP
|
52
include/TreeOfShapesGeraud/ToSutils.hpp
Normal file
52
include/TreeOfShapesGeraud/ToSutils.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef TOSUTILS_HPP
|
||||
#define TOSUTILS_HPP
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
|
||||
#define X first
|
||||
#define Y second
|
||||
#define coord first
|
||||
#define pxdir second.first
|
||||
#define pxtype second.second
|
||||
|
||||
#define F first
|
||||
#define S second
|
||||
#define lower first
|
||||
#define upper second
|
||||
|
||||
#define make_pxCoord(x,y) std::make_pair((x), (y))
|
||||
#define make_pxDirected(px,dir,type) std::make_pair((px),std::make_pair((dir),(type)))
|
||||
|
||||
namespace otb {
|
||||
|
||||
enum pxType {regular, dual};
|
||||
|
||||
typedef std::pair<int, int> pxCoord;
|
||||
typedef std::pair <pxCoord, std::pair<int, pxType>> pxDirected;
|
||||
|
||||
// XXX
|
||||
|
||||
class CompareByX{public: bool operator() (const pxCoord &lhs, const pxCoord &rhs); };
|
||||
|
||||
class CompareByY{public: bool operator() (const pxCoord &lhs, const pxCoord &rhs); };
|
||||
|
||||
pxCoord
|
||||
nextCoord(pxDirected &dpx);
|
||||
|
||||
bool
|
||||
coordOk(const pxCoord &coord, int imgCols, int imgRows);
|
||||
|
||||
bool
|
||||
nextDir(const pxDirected &dpx);
|
||||
|
||||
double
|
||||
getCvMatElem(const cv::Mat &img, const std::pair<int, int> &coord);
|
||||
|
||||
double
|
||||
getCvMatElem(const cv::Mat &img, int X, int Y);
|
||||
|
||||
}
|
||||
|
||||
#endif // TOSUTILS_HPP
|
39
include/XMLTree/XMLTreeBuilder.hpp
Normal file
39
include/XMLTree/XMLTreeBuilder.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
#ifndef XMLTREEBUILDER_HPP
|
||||
#define XMLTREEBUILDER_HPP
|
||||
|
||||
#include <tinyxml.h>
|
||||
|
||||
#include "BuildTree.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
class XMLTreeBuilder : public BuildTree {
|
||||
|
||||
public:
|
||||
XMLTreeBuilder(const std::string &fileN) : fileName(fileN) {}
|
||||
|
||||
void
|
||||
buildTree(Tree &tree);
|
||||
|
||||
static void
|
||||
exportToFile(const Tree &tree, const std::string &fileName);
|
||||
|
||||
void
|
||||
exportToFile(const Tree &tree) const { return exportToFile(tree, fileName); }
|
||||
|
||||
private:
|
||||
static void
|
||||
writeNodeChildren(const Tree &tree, const DimNodeId &id, TiXmlElement *node);
|
||||
|
||||
DimNodeId
|
||||
getNodeCount(const TiXmlElement *node);
|
||||
|
||||
void
|
||||
readNodeChildren(const TiXmlElement *node, DimNodeId &id);
|
||||
|
||||
private:
|
||||
std::string fileName;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // XMLTREEBUILDER_HPP
|
71
include/baseDef.hpp
Normal file
71
include/baseDef.hpp
Normal file
@ -0,0 +1,71 @@
|
||||
#ifndef BASE_OTREE
|
||||
#define BASE_OTREE
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
|
||||
#define DimImg_MAX UINT32_MAX
|
||||
|
||||
namespace otb {
|
||||
|
||||
// ========================
|
||||
|
||||
/*! Image size type */
|
||||
typedef uint32_t DimSideImg;
|
||||
|
||||
/*! Number of pixels */
|
||||
typedef uint32_t DimImg;
|
||||
|
||||
/*! Number of nodes */
|
||||
typedef uint32_t DimNodeId;
|
||||
|
||||
// =======================
|
||||
|
||||
struct Point {
|
||||
DimSideImg x, y;
|
||||
Point() : x(0), y(0) {}
|
||||
Point(const DimSideImg &abs, const DimSideImg &ord) : x(abs), y(ord) {}
|
||||
};
|
||||
inline std::ostream &operator << (std::ostream &out, const Point &p) { return out << "(" << p.x << "," << p.y << ")"; }
|
||||
|
||||
struct Size {
|
||||
DimSideImg width, height;
|
||||
Size() : width(0), height(0) {}
|
||||
Size(const DimSideImg &w, const DimSideImg &h) : width(w), height(h) {}
|
||||
};
|
||||
inline std::ostream &operator << (std::ostream &out, const Size &s) { return out << "[" << s.width << "," << s.height << "]"; }
|
||||
|
||||
inline DimImg pointToId(const Size &size, const Point &p) { return (DimImg)p.x + (DimImg)p.y * size.width; }
|
||||
|
||||
inline Point idToPoint(const Size &size, const DimImg &id) { return Point(id % size.width, id / size.width); }
|
||||
|
||||
struct Rect {
|
||||
DimSideImg x, y, width, height;
|
||||
Rect() : x(0), y(0), width(0), height(0) {}
|
||||
Rect(const Rect &rect) : x(rect.x), y (rect.y), width(rect.width), height(rect.height) {}
|
||||
Rect(const Point &orig, const Size &size) : x(orig.x), y(orig.y), width(size.width), height(size.height) {}
|
||||
Rect(const DimSideImg &abs, const DimSideImg &ord, const DimSideImg &w, const DimSideImg &h) :
|
||||
x(abs), y(ord), width(w), height(h) {}
|
||||
};
|
||||
inline std::ostream &operator << (std::ostream &out, const Rect &r) {
|
||||
return out << "[" << r.x << "," << r.y << " " << r.width << "x" << r.height << "]";
|
||||
}
|
||||
|
||||
// =======================
|
||||
|
||||
|
||||
template <typename DimImg>
|
||||
inline std::ostream &printMap(std::ostream &out, const DimImg *map, const Size &size) {
|
||||
for (DimSideImg y = 0; y < size.height; ++y) {
|
||||
for (DimSideImg x = 0; x < size.width; ++x, ++map)
|
||||
out << std::setw(3) << *map;
|
||||
out << std::endl;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
} // namespace Obelix
|
||||
|
||||
#endif // BASE_OTREE
|
170
include/dealThreads.hpp
Normal file
170
include/dealThreads.hpp
Normal file
@ -0,0 +1,170 @@
|
||||
#ifndef DEALTHREADS_HPP
|
||||
#define DEALTHREADS_HPP
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
namespace otb {
|
||||
namespace utils {
|
||||
|
||||
template<typename DimImg, typename FunctId>
|
||||
inline void
|
||||
dealThreadRange (const DimImg &maxId, const unsigned int &coreCount, const FunctId &functId/* functId (id) */);
|
||||
|
||||
template<typename DimImg, typename FunctThreadId>
|
||||
inline void
|
||||
dealThreadThreadRange (const DimImg &maxId, const unsigned int &coreCount, const FunctThreadId &functThreadId/* functThreadId (threadId, id) */);
|
||||
|
||||
template<typename DimImg, typename FunctMinMax>
|
||||
inline void
|
||||
dealThreadBound (const DimImg &maxId, const unsigned int &coreCount, const FunctMinMax &functMinMax/* functMinMax (minVal, maxVal) */);
|
||||
|
||||
template<typename DimImg>
|
||||
inline std::vector<DimImg>
|
||||
getDealThreadBounds (const DimImg &maxId, const unsigned int &coreCount);
|
||||
|
||||
template<typename DimImg, typename FunctThreadMinMax>
|
||||
inline void
|
||||
dealThread (const DimImg &maxId, unsigned int coreCount, const FunctThreadMinMax &functThreadMinMax/* functThreadMinMax (threadId, minVal, maxVal) */);
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename DimImg, typename WeightT, typename WeightFunct, typename CmpFunct, typename CallFunct>
|
||||
inline void
|
||||
callOnSortedSets (const std::vector<DimImg> &sizes,
|
||||
const WeightFunct &getWeight/* getWeight (vectId, itemId) */,
|
||||
CmpFunct isWeightInf/* isWeightInf (w1, w2) */,
|
||||
const CallFunct &callIdId/* callIdId (vectId, itemId) */);
|
||||
|
||||
// ========================================
|
||||
template<typename DimImg, typename FunctId>
|
||||
inline void
|
||||
dealThreadRange (const DimImg &maxId, const unsigned int &coreCount, const FunctId &functId/* functId (id) */) {
|
||||
dealThread (maxId, coreCount, [&functId] (const unsigned int &threadId, const DimImg &minVal, const DimImg &maxVal) {
|
||||
for (DimImg id = minVal; id < maxVal; ++id)
|
||||
functId (id);
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename DimImg, typename FunctThreadId>
|
||||
inline void
|
||||
dealThreadThreadRange (const DimImg &maxId, const unsigned int &coreCount, const FunctThreadId &functThreadId/* functThreadId (threadId, id) */) {
|
||||
dealThread (maxId, coreCount, [&functThreadId] (const unsigned int &threadId, const DimImg &minVal, const DimImg &maxVal) {
|
||||
for (DimImg id = minVal; id < maxVal; ++id)
|
||||
functThreadId (threadId, id);
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename DimImg, typename FunctMinMax>
|
||||
inline void
|
||||
dealThreadBound (const DimImg &maxId, const unsigned int &coreCount, const FunctMinMax &functMinMax/* functMinMax (minVal, maxVal) */) {
|
||||
dealThread (maxId, coreCount, [&functMinMax] (const unsigned int &threadId, const DimImg &minVal, const DimImg &maxVal) {
|
||||
functMinMax (minVal, maxVal);
|
||||
});
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename DimImg>
|
||||
inline std::vector<DimImg>
|
||||
getDealThreadBounds (const DimImg &maxId, const unsigned int &coreCount) {
|
||||
if (!maxId || !coreCount)
|
||||
return std::vector<DimImg> (0);
|
||||
DimImg average = maxId/coreCount;
|
||||
std::vector<DimImg> maxIds (coreCount+1, average);
|
||||
|
||||
for (unsigned int core = 0; core < coreCount; ++core)
|
||||
maxIds[core] = DimImg (core*average);
|
||||
maxIds[coreCount] = maxId;
|
||||
return maxIds;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template<typename DimImg, typename FunctThreadMinMax>
|
||||
inline void
|
||||
dealThread (const DimImg &maxId, unsigned int coreCount, const FunctThreadMinMax &functThreadMinMax/* functThreadMinMax (threadId, minVal, maxVal) */) {
|
||||
//DEF_LOG ("dealThreadBound", "coreCount:" << coreCount << " maxId:" << maxId);
|
||||
if (!maxId || !coreCount)
|
||||
return;
|
||||
if (DimImg (coreCount) > maxId)
|
||||
coreCount = (unsigned int) maxId;
|
||||
if (coreCount == 1) {
|
||||
functThreadMinMax (0, 0, maxId);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<DimImg> maxIds = getDealThreadBounds (maxId, coreCount);
|
||||
boost::thread tasks [coreCount];
|
||||
for (unsigned int idCopyValInThread = 0; idCopyValInThread < coreCount; ++idCopyValInThread) {
|
||||
tasks[idCopyValInThread] = boost::thread ([/*no ref!!!*/idCopyValInThread, &maxIds, &functThreadMinMax] () {
|
||||
functThreadMinMax (idCopyValInThread, maxIds[idCopyValInThread], maxIds[idCopyValInThread+1]);
|
||||
});
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < coreCount; ++i)
|
||||
tasks[i].join ();
|
||||
}
|
||||
|
||||
// ========================================
|
||||
template<typename DimImg, typename WeightT, typename WeightFunct, typename CmpFunct, typename CallFunct>
|
||||
inline void
|
||||
callOnSortedSets (const std::vector<DimImg> &sizes,
|
||||
const WeightFunct &getWeight/* getWeight (vectId, itemId) */,
|
||||
CmpFunct isWeightInf/* isWeightInf (w1, w2) */,
|
||||
const CallFunct &callIdId/* callIdId (vectId, itemId) */) {
|
||||
DimImg size = sizes.size ();
|
||||
DEF_LOG ("callOnSortedSets", "size:" << size);
|
||||
if (!size)
|
||||
return;
|
||||
std::vector<DimImg> vectIds (size, 0);
|
||||
std::vector<DimImg> vectCounts (sizes);
|
||||
// get min
|
||||
bool found = false;
|
||||
DimImg minVectIdx = 0;
|
||||
WeightT minWeight = 0;
|
||||
for (DimImg vectId = 0; vectId < size; ++vectId) {
|
||||
if (!vectCounts [vectId])
|
||||
continue;
|
||||
WeightT tmpWeight = getWeight (vectId, 0);
|
||||
if (found && !isWeightInf (tmpWeight, minWeight))
|
||||
continue;
|
||||
minVectIdx = vectId;
|
||||
minWeight = tmpWeight;
|
||||
found = true;
|
||||
}
|
||||
LOG ("found:" << found << " minVectIdx:" << minVectIdx << " minWeight:" << minWeight);
|
||||
// loop
|
||||
for ( ; found; ) {
|
||||
// get next min
|
||||
found = false;
|
||||
DimImg nextMinVectIdx = 0;
|
||||
WeightT nextMinWeight = 0;
|
||||
for (DimImg vectId = minVectIdx; ; ) {
|
||||
if (vectCounts [vectId]) {
|
||||
WeightT tmpWeight = getWeight (vectId, vectIds [vectId]);
|
||||
if (!isWeightInf (minWeight, tmpWeight)) {
|
||||
// minWeight == tmpWeight
|
||||
callIdId (vectId, vectIds [vectId]);
|
||||
++vectIds [vectId];
|
||||
--vectCounts [vectId];
|
||||
continue;
|
||||
}
|
||||
if (!found || isWeightInf (tmpWeight, nextMinWeight)) {
|
||||
nextMinVectIdx = vectId;
|
||||
nextMinWeight = tmpWeight;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
vectId = (vectId+1)%size;
|
||||
if (vectId == minVectIdx)
|
||||
break;
|
||||
}
|
||||
minVectIdx = nextMinVectIdx;
|
||||
minWeight = nextMinWeight;
|
||||
}
|
||||
}
|
||||
|
||||
} // utils
|
||||
} // otb
|
||||
|
||||
|
||||
#endif // DEALTHREADS_HPP
|
61
include/debug.hpp
Normal file
61
include/debug.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef _debug_hpp
|
||||
#define _debug_hpp
|
||||
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#ifdef SMART_LOG
|
||||
|
||||
#ifndef DEF_LOG
|
||||
#define DEF_LOG(name, expr) ::utils::Log log (name); { std::cerr << expr << std::endl << std::flush; }
|
||||
#define DEF_L(name) DEF_LOG(name, "")
|
||||
#endif
|
||||
|
||||
#ifndef LOG
|
||||
#define LOG(expr) { std::cerr << log << "| " << expr << std::endl << std::flush; }
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG(expr) { std::cerr << expr << std::endl << std::flush; }
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef DEF_LOG
|
||||
#define DEF_LOG(name, expr)
|
||||
#define DEF_L(name)
|
||||
#endif
|
||||
|
||||
#ifndef LOG
|
||||
#define LOG(expr)
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG
|
||||
#define DEBUG(expr)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace utils {
|
||||
|
||||
// ========================================
|
||||
using namespace std;
|
||||
|
||||
class Log {
|
||||
static unsigned int indent;
|
||||
string functName;
|
||||
public:
|
||||
Log (const string &funct) : functName (funct) { ++indent; cerr << *this << "> "; }
|
||||
~Log () { cerr << *this << "<" << endl << flush; --indent; }
|
||||
friend inline ostream &operator << (ostream &out, const Log &log) {
|
||||
return out << setw (3) << setw ((log.indent % 20)*2) << "" << log.functName;
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================
|
||||
}//namespace utils
|
||||
|
||||
#endif //_debug_hpp
|
77
include/getType.hpp
Normal file
77
include/getType.hpp
Normal file
@ -0,0 +1,77 @@
|
||||
#ifndef GETTYPE_HPP
|
||||
#define GETTYPE_HPP
|
||||
|
||||
#include <gdal/gdal_priv.h>
|
||||
|
||||
namespace otb {
|
||||
|
||||
enum DataType {
|
||||
Unknown = 0,
|
||||
Byte = 1 << 0,
|
||||
UInt16 = 1 << 1,
|
||||
Int16 = 1 << 2,
|
||||
UInt32 = 1 << 3,
|
||||
Int32 = 1 << 4,
|
||||
Float = 1 << 5,
|
||||
Double = 1 << 6
|
||||
};
|
||||
|
||||
template<typename Type>
|
||||
DataType
|
||||
getType(Type v) { return DataType::Unknown; };
|
||||
|
||||
template<>
|
||||
DataType
|
||||
getType<uint8_t>(uint8_t v) { return DataType::Byte; };
|
||||
|
||||
template<>
|
||||
DataType
|
||||
getType<uint16_t>(uint16_t v) { return DataType::UInt16; };
|
||||
|
||||
template<>
|
||||
DataType
|
||||
getType<int16_t>(int16_t v) { return DataType::Int16; };
|
||||
|
||||
template<>
|
||||
DataType
|
||||
getType<uint32_t>(uint32_t v) { return DataType::UInt32; };
|
||||
|
||||
template<>
|
||||
DataType
|
||||
getType<int32_t>(int32_t v) { return DataType::Int32; };
|
||||
|
||||
template<>
|
||||
DataType
|
||||
getType<float>(float v) { return DataType::Float; };
|
||||
|
||||
template<>
|
||||
DataType
|
||||
getType<double>(double v) { return DataType::Double; };
|
||||
|
||||
// =====================
|
||||
|
||||
GDALDataType
|
||||
toGDALType(DataType type) {
|
||||
switch(type) {
|
||||
case DataType::Byte:
|
||||
return GDT_Byte;
|
||||
case DataType::UInt16:
|
||||
return GDT_UInt16;
|
||||
case DataType::Int16:
|
||||
return GDT_Int16;
|
||||
case DataType::UInt32:
|
||||
return GDT_UInt32;
|
||||
case DataType::Int32:
|
||||
return GDT_Int32;
|
||||
case DataType::Float:
|
||||
return GDT_Float32;
|
||||
case DataType::Double:
|
||||
return GDT_Float64;
|
||||
default:
|
||||
return GDT_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // GETTYPE_HPP
|
1
otb-module.cmake
Normal file
1
otb-module.cmake
Normal file
@ -0,0 +1 @@
|
||||
otb_module(TreeBuilder DEPENDS OTBTinyXML OTBOpenCV DESCRIPTION "A description string")
|
28
src/Attribute.cpp
Normal file
28
src/Attribute.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "Attribute.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
Attribute::free() {
|
||||
delete[] (T*) attributes;
|
||||
attributes = nullptr;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T
|
||||
Attribute::getAttribute(const DimNodeId &nodeId) {
|
||||
return ((T*)attributes)[nodeId];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
Attribute::generate() {
|
||||
attributes = new T[tree->getLeafCount() + tree->getNodeCount()];
|
||||
generate();
|
||||
}
|
||||
|
||||
void
|
||||
Attribute::setTree(Tree &treeC) { tree = &treeC; }
|
||||
|
||||
} // otb
|
12
src/Attributes/AreaAttribute.cpp
Normal file
12
src/Attributes/AreaAttribute.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
#include "Attributes/AreaAttribute.hpp"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace otb {
|
||||
|
||||
void
|
||||
AreaAttribute::generate() {
|
||||
DimNodeId root = tree->getRoot();
|
||||
}
|
||||
|
||||
} // otb
|
21
src/CMakeLists.txt
Normal file
21
src/CMakeLists.txt
Normal file
@ -0,0 +1,21 @@
|
||||
set(OTBTreeBuilder_SRC
|
||||
Attribute.cpp
|
||||
debug.cpp
|
||||
testMain.cpp
|
||||
Tree.cpp
|
||||
Attributes/AreaAttribute.cpp
|
||||
DAPTree/baseDAPTree.cpp
|
||||
DAPTree/GraphWalker.cpp
|
||||
DAPTree/ParRnk.cpp
|
||||
DAPTree/sort.cpp
|
||||
QuadTree/QuadTreeBuilder.cpp
|
||||
TreeOfShapesGeraud/ToSBuilder.cpp
|
||||
TreeOfShapesGeraud/ToSutils.cpp
|
||||
XMLTree/XMLTreeBuilder.cpp
|
||||
)
|
||||
|
||||
add_library(OTBTreeBuilder ${OTBTreeBuilder_SRC})
|
||||
|
||||
target_link_libraries(OTBTreeBuilder ${OTBTinyXML_LIBRARIES} ${OTBOpenCV_LIBRARIES})
|
||||
|
||||
otb_module_target(OTBTreeBuilder)
|
315
src/DAPTree/GraphWalker.cpp
Normal file
315
src/DAPTree/GraphWalker.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
#include "DAPTree/GraphWalker.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
// ========================================
|
||||
DimImg
|
||||
GraphWalker::vertexMaxCount () const {
|
||||
return vertexMaxCount (size);
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
DimImg
|
||||
GraphWalker::vertexMaxCount (const Size &tileSize) const {
|
||||
return DimImg (tileSize.width)*DimImg (tileSize.height);
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
DimEdge
|
||||
GraphWalker::edgeMaxCount () const {
|
||||
return edgeMaxCount (size);
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
DimEdge
|
||||
GraphWalker::edgeMaxCount (const Size &tileSize) const {
|
||||
if (!tileSize.width || !tileSize.height)
|
||||
return 0;
|
||||
DimEdge miniSquare = DimImg (tileSize.width)*DimImg (tileSize.height-1) + DimImg (tileSize.width-1)*DimImg (tileSize.height);
|
||||
switch (connectivity) {
|
||||
case Connectivity::C4 :
|
||||
return miniSquare;
|
||||
case Connectivity::C6N :
|
||||
case Connectivity::C6P :
|
||||
return miniSquare + DimImg (tileSize.width-1)*DimImg (tileSize.height-1);
|
||||
default :
|
||||
BOOST_ASSERT (connectivity == Connectivity::C8);
|
||||
return miniSquare + 2*DimImg (tileSize.width-1)*DimImg (tileSize.height-1);
|
||||
};
|
||||
}
|
||||
// ----------------------------------------
|
||||
DimEdge
|
||||
GraphWalker::edgeBoundaryMaxCount (const DimSideImg &side) const {
|
||||
if (!side)
|
||||
return 0;
|
||||
switch (connectivity) {
|
||||
case Connectivity::C4 :
|
||||
return side;
|
||||
case Connectivity::C6N :
|
||||
case Connectivity::C6P :
|
||||
return side+side-1;
|
||||
default :
|
||||
BOOST_ASSERT (connectivity == Connectivity::C8);
|
||||
return 3*side-2;
|
||||
};
|
||||
}
|
||||
|
||||
// ========================================
|
||||
void
|
||||
GraphWalker::setTiles (const unsigned int &coreCount, const Rect &tile,
|
||||
std::vector<Rect> &tiles, std::vector<Rect> &boundaries, std::vector<bool> &verticalBoundaries) const {
|
||||
BOOST_ASSERT (coreCount);
|
||||
DEF_LOG ("GraphWalker::setTiles", "coreCount:" << coreCount << " tile:" << tile);
|
||||
if (coreCount < 2 || std::max (tile.width, tile.height) < 4 || std::min (tile.width, tile.height) < 3) {
|
||||
LOG ("tile:" << tile);
|
||||
tiles.push_back (tile);
|
||||
return;
|
||||
}
|
||||
bool vertical = tile.width > tile.height;
|
||||
bool odd = coreCount & 0x1;
|
||||
DimImg thin = (vertical ? tile.width : tile.height) / (odd ? coreCount : 2);
|
||||
Rect tileA (tile);
|
||||
Rect tileB (tile);
|
||||
if (vertical) {
|
||||
tileA.width = thin;
|
||||
tileB.x += thin;
|
||||
tileB.width -= thin;
|
||||
} else {
|
||||
tileA.height = thin;
|
||||
tileB.y += thin;
|
||||
tileB.height -= thin;
|
||||
}
|
||||
setTiles ((odd ? 1 : coreCount/2), tileA, tiles, boundaries, verticalBoundaries);
|
||||
boundaries.push_back (tileB);
|
||||
verticalBoundaries.push_back (vertical);
|
||||
setTiles ((odd ? coreCount-1 : coreCount/2), tileB, tiles, boundaries, verticalBoundaries);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
template<typename Funct>
|
||||
DimImg
|
||||
GraphWalker::forEachVertexIdx (const Funct &lambda /*lambda (idx)*/) const {
|
||||
DimImg maxCount = vertexMaxCount ();
|
||||
DimImg vertexCount = 0;
|
||||
for (DimSideImg idx = 0; idx < maxCount; ++idx)
|
||||
GRAPHWALKER_CALL_LAMBDA_IDX (idx, vertexCount, lambda (idx));
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
template<typename Funct>
|
||||
DimImg
|
||||
GraphWalker::forEachVertexPt (const Funct &lambda /*lambda (p)*/) const {
|
||||
return forEachVertexIdx ([this, &lambda] (const Point &p) { lambda (pointToId (size, p)); });
|
||||
}
|
||||
|
||||
template<typename Funct>
|
||||
DimImg
|
||||
GraphWalker::forEachVertexIdx (const Rect &rect, const Funct &lambda /*lambda (idx)*/) const {
|
||||
DimImg vertexCount = 0;
|
||||
DimSideImg const lastX = rect.x+rect.width;
|
||||
DimSideImg const lastY = rect.y+rect.height;
|
||||
for (DimSideImg y = rect.y; y < lastY; ++y)
|
||||
for (DimSideImg x = rect.x; x < lastX; ++x) {
|
||||
const Point p (x, y);
|
||||
DimImg idx = pointToId(size, p);
|
||||
GRAPHWALKER_CALL_LAMBDA_IDX (idx, vertexCount, lambda (idx));
|
||||
}
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
template<typename Funct>
|
||||
DimImg
|
||||
GraphWalker::forEachVertexPt (const Rect &rect, const Funct &lambda /*lambda (p)*/) const {
|
||||
DimImg vertexCount = 0;
|
||||
DimSideImg const lastX = rect.x+rect.width;
|
||||
DimSideImg const lastY = rect.y+rect.height;
|
||||
for (DimSideImg y = rect.y; y < lastY; ++y)
|
||||
for (DimSideImg x = rect.x; x < lastX; ++x) {
|
||||
const Point p (x, y);
|
||||
DimImg idx = pointToId(size, p);
|
||||
GRAPHWALKER_CALL_LAMBDA_IDX (idx, vertexCount, lambda (p));
|
||||
}
|
||||
return vertexCount;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
template<typename Funct>
|
||||
DimEdge
|
||||
GraphWalker::forEachEdgePt (const Rect &rect, TileItem tileItem, const Funct &lambda /*lambda (p0, p1)*/) const {
|
||||
DimImg edgeCount = 0;
|
||||
if (!rect.width || !rect.height)
|
||||
return edgeCount;
|
||||
const DimSideImg firstX = rect.x, endX = rect.x+rect.width;
|
||||
const DimSideImg firstY = rect.y, endY = rect.y+rect.height;
|
||||
switch (tileItem) {
|
||||
|
||||
case Surface:
|
||||
{
|
||||
for (DimSideImg x = firstX+1; x < endX; ++x) {
|
||||
Point pha1 (x-1, firstY), pha2 (x, firstY);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (pha1, pha2, edgeCount, lambda (pha1, pha2));
|
||||
}
|
||||
for (DimSideImg y = firstY+1; y < endY; ++y) {
|
||||
Point pva1 (firstX, y-1), pva2 (firstX, y);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (pva1, pva2, edgeCount, lambda (pva1, pva2));
|
||||
for (DimSideImg x = firstX+1; x < endX; ++x) {
|
||||
Point ph1 (x-1, y), pv1 (x, y-1), p2 (x, y);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (ph1, p2, edgeCount, lambda (ph1, p2));
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (pv1, p2, edgeCount, lambda (pv1, p2));
|
||||
}
|
||||
}
|
||||
if (connectivity & Connectivity::C6P)
|
||||
for (DimSideImg y = firstY+1; y < endY; ++y)
|
||||
for (DimSideImg x = firstX+1; x < endX; ++x) {
|
||||
Point p1 (x-1, y-1), p2 (x, y);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
|
||||
}
|
||||
if (connectivity & Connectivity::C6N)
|
||||
for (DimSideImg y = firstY+1; y < endY; ++y)
|
||||
for (DimSideImg x = firstX+1; x < endX; ++x) {
|
||||
Point p1 (x-1, y), p2 (x, y-1);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Horizontal:
|
||||
{
|
||||
const DimSideImg y1 = rect.y-1, y2 = rect.y;
|
||||
for (DimSideImg x = firstX; x < endX; ++x) {
|
||||
Point p1 (x, y1), p2 (x, y2);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
|
||||
}
|
||||
if (connectivity & Connectivity::C6P)
|
||||
for (DimSideImg x = firstX+1; x < endX; ++x) {
|
||||
Point p1 (x-1, y1), p2 (x, y2);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
|
||||
}
|
||||
if (connectivity & Connectivity::C6N)
|
||||
for (DimSideImg x = firstX+1; x < endX; ++x) {
|
||||
Point p1 (x, y1), p2 (x-1, y2);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Vertical:
|
||||
{
|
||||
const DimSideImg x1 = rect.x-1, x2 = rect.x;
|
||||
for (DimSideImg y = firstY; y < endY; ++y) {
|
||||
Point p1 (x1, y), p2 (x2, y);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
|
||||
}
|
||||
if (connectivity & Connectivity::C6P)
|
||||
for (DimSideImg y = firstY+1; y < endY; ++y) {
|
||||
Point p1 (x1, y-1), p2 (x2, y);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
|
||||
}
|
||||
if (connectivity & Connectivity::C6N)
|
||||
for (DimSideImg y = firstY+1; y < endY; ++y) {
|
||||
Point p1 (x1, y), p2 (x2, y-1);
|
||||
GRAPHWALKER_CALL_LAMBDA_PTS (p1, p2, edgeCount, lambda (p1, p2));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BOOST_ASSERT (false);
|
||||
}
|
||||
return edgeCount;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
template <typename WeightT, typename EdgeWeightFunction>
|
||||
WeightT
|
||||
GraphWalker::getMedian (const EdgeWeightFunction &ef /*ef.getValue (idx)*/) const {
|
||||
int bits = 8*sizeof (WeightT);
|
||||
BOOST_ASSERT (bits < 17);
|
||||
DimEdge dim = 1UL << bits;
|
||||
std::vector<DimImg> indices (dim+1, 0);
|
||||
DimImg *histogram = &indices[1];
|
||||
forEachVertexIdx ([&histogram, &ef] (const DimImg &idx) {
|
||||
++histogram[(size_t) ef.getValue (idx)];
|
||||
});
|
||||
std::partial_sum (histogram, histogram+dim, histogram);
|
||||
return std::lower_bound (indices.begin (), indices.end (), indices[dim] >> 1) - indices.begin ();
|
||||
}
|
||||
|
||||
// ========================================
|
||||
template <typename WeightT, typename EdgeWeightFunction>
|
||||
DimEdge
|
||||
GraphWalker::getEdges (const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1)*/) const {
|
||||
BOOST_ASSERT (rect.width);
|
||||
BOOST_ASSERT (rect.height);
|
||||
BOOST_ASSERT (edges);
|
||||
DimEdge edgeCount = 0;
|
||||
forEachEdgePt (rect, tileItem,
|
||||
[&edges, &edgeCount, &ef] (Point const &a, Point const &b) {
|
||||
Edge<WeightT> &edge = edges[edgeCount++];
|
||||
edge.points[0] = a;
|
||||
edge.points[1] = b;
|
||||
edge.weight = ef.getWeight (a, b);
|
||||
});
|
||||
return edgeCount;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
template <typename WeightT, typename EdgeWeightFunction>
|
||||
DimEdge
|
||||
GraphWalker::getSortedEdges (const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1) ef.sort ()*/) const {
|
||||
DimEdge edgeCount = getEdges (rect, tileItem, edges, ef);
|
||||
ef.sort (edges, edgeCount);
|
||||
return edgeCount;
|
||||
}
|
||||
|
||||
template <typename WeightT, typename EdgeWeightFunction>
|
||||
// template DimImg
|
||||
DimEdge
|
||||
GraphWalker::getCountingSortedEdges (const Rect &rect, TileItem tileItem, Edge<WeightT> *edges, const EdgeWeightFunction &ef /*ef.getWeight (p0, p1)*/) const {
|
||||
int bits = 8*sizeof (WeightT);
|
||||
BOOST_ASSERT (bits < 17);
|
||||
DimEdge dim = 1UL << bits;
|
||||
DimImg *indices = new DimImg [dim+1];
|
||||
DimImg *histogram = indices+1;
|
||||
DimImg sum = 0;
|
||||
::std::fill_n (histogram, dim, 0);
|
||||
forEachEdgePt (rect, tileItem,
|
||||
[&histogram, &ef] (Point const &a, Point const &b) {
|
||||
++histogram[(size_t) ef.getWeight (a, b)];
|
||||
});
|
||||
|
||||
// get indices by prefix sum
|
||||
std::partial_sum (histogram, histogram+dim, histogram);
|
||||
sum = indices[dim];
|
||||
if (ef.getDecr ()) {
|
||||
for (size_t i = 0; i < dim; ++i)
|
||||
histogram[i] = sum - histogram[i];
|
||||
indices++;
|
||||
} else
|
||||
indices[0] = 0;
|
||||
// extract edges
|
||||
forEachEdgePt (rect, tileItem,
|
||||
[
|
||||
#ifdef SMART_LOG
|
||||
this,
|
||||
#endif
|
||||
&ef, &edges, &indices] (Point const &a, Point const &b) {
|
||||
WeightT weight = ef.getWeight (a, b);
|
||||
Edge<WeightT> &edge = edges[indices[(size_t) weight]++];
|
||||
edge.points[0] = a;
|
||||
edge.points[1] = b;
|
||||
edge.weight = weight;
|
||||
#ifdef SMART_LOG
|
||||
printEdge (cerr, edge, size) << endl;
|
||||
#endif
|
||||
});
|
||||
#ifdef SMART_LOG
|
||||
cerr << endl;
|
||||
for (int i = 0; i < sum; ++i)
|
||||
printEdge (cerr, edges[i], size) << endl;
|
||||
#endif
|
||||
delete [] (histogram-1);
|
||||
return sum;
|
||||
}
|
||||
|
||||
} // otb
|
110
src/DAPTree/ParRnk.cpp
Normal file
110
src/DAPTree/ParRnk.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "DAPTree/ParRnk.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
// ========================================
|
||||
DimImg
|
||||
ParRnk::find (DimImg a) const {
|
||||
BOOST_ASSERT (a < size);
|
||||
for (;;) {
|
||||
// On recherche le parent de a dans le tableau
|
||||
DimImg p = parent[a];
|
||||
// Si p est size, p n'a pas de parent donc p était le parent de a
|
||||
if (p == DimImg_MAX)
|
||||
break;
|
||||
a = p;
|
||||
}
|
||||
BOOST_ASSERT (a < size);
|
||||
return a;
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
void
|
||||
ParRnk::link (DimImg a, const DimImg &r) {
|
||||
BOOST_ASSERT (a < size);
|
||||
BOOST_ASSERT (r < size);
|
||||
for (;;) {
|
||||
// Si a et r sont le même pixel, alors ils sont liés
|
||||
if (a == r)
|
||||
return;
|
||||
// On affecte une variable "temporaire" qui joue le rôle du parent de a
|
||||
DimImg p = parent[a];
|
||||
//
|
||||
parent[a] = r;
|
||||
if (p == DimImg_MAX)
|
||||
return;
|
||||
a = p;
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
void
|
||||
ParRnk::book (DimImg vertexCount) {
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("ParRnk::book", "vertexCount:" << vertexCount);
|
||||
#endif
|
||||
if (vertexCount == size) {
|
||||
reset ();
|
||||
return;
|
||||
}
|
||||
free ();
|
||||
if (!vertexCount)
|
||||
return;
|
||||
size = vertexCount;
|
||||
count = new DimImg [vertexCount];
|
||||
parent = new DimImg [vertexCount];
|
||||
reset ();
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
void
|
||||
ParRnk::reset () {
|
||||
if (!size)
|
||||
return;
|
||||
std::fill_n (count, size, 1);
|
||||
std::fill_n (parent, size, DimImg_MAX);
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
void
|
||||
ParRnk::free () {
|
||||
#ifdef SMART_LOG
|
||||
DEF_LOG ("ParRnk::free", "");
|
||||
#endif
|
||||
if (parent)
|
||||
delete [] parent;
|
||||
if (count)
|
||||
delete [] count;
|
||||
count = parent = NULL;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
// ========================================
|
||||
DimImg
|
||||
ParRnk::linkParent (DimImg maxLevel, DimImg minLevel, const bool &same,
|
||||
const DimImg &a, const DimImg &b) {
|
||||
//DEF_LOG ("ParRnk::linkParent", "maxLevel:" << maxLevel << " minLevel:" << minLevel << " diff:" << diff);
|
||||
BOOST_ASSERT (maxLevel != minLevel);
|
||||
BOOST_ASSERT (maxLevel < size);
|
||||
BOOST_ASSERT (minLevel < size);
|
||||
BOOST_ASSERT (parent[maxLevel] == DimImg_MAX);
|
||||
BOOST_ASSERT (parent[minLevel] == DimImg_MAX);
|
||||
// Si maxLevel et minLevel ont le même niveau, on vérifie celui qui a le plus de fils pour en faire le nouveau père
|
||||
if (same && count [maxLevel] < count [minLevel])
|
||||
std::swap (maxLevel, minLevel);
|
||||
|
||||
// Si maxLevel et minLevel ont le même niveau, alors le compteur de fils de minLevel s'ajoute à celui de maxLevel, sinon on incrémente le nombre de file de maxLevel
|
||||
count [maxLevel] += same ? count [minLevel] : 1;
|
||||
|
||||
// Le nouveau père de minLevel est maxLevel
|
||||
parent [minLevel] = maxLevel;
|
||||
//LOG ("maxLevel:" << maxLevel << " minLevel:" << minLevel << " diff:" << diff);
|
||||
|
||||
// On effectue les mises à jour des pères sur a et b
|
||||
link (a, maxLevel);
|
||||
link (b, maxLevel);
|
||||
return maxLevel;
|
||||
}
|
||||
|
||||
|
||||
} // otb
|
21
src/DAPTree/baseDAPTree.cpp
Normal file
21
src/DAPTree/baseDAPTree.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "DAPTree/baseDAPTree.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
int bitCount [] = {
|
||||
0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
|
||||
3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
|
||||
};
|
||||
|
||||
std::string connectivityName[] = {"C4", "C6P", "C6N", "C8"};
|
||||
std::string tileItemName[] = {"Surface", "Horizontal", "Vertical"};
|
||||
std::string treeName[] = {"min", "max", "tos"};
|
||||
|
||||
|
||||
} // otb
|
47
src/DAPTree/sort.cpp
Normal file
47
src/DAPTree/sort.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "DAPTree/sort.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace otb {
|
||||
|
||||
template <typename T>
|
||||
inline std::vector<T> getRandReduce(std::vector<T> index, T reduceCount) {
|
||||
T size = index.size ();
|
||||
if (reduceCount >= size)
|
||||
return index;
|
||||
for (T i = 0; i < size; ++i) {
|
||||
T j = rand() % size;
|
||||
T tmp = index [i];
|
||||
index [i] = index [j];
|
||||
index [j] = tmp;
|
||||
}
|
||||
std::vector<T> result (&index [0], &index[reduceCount]);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename E, typename WeightT, typename DimImg, typename WeightFunct>
|
||||
inline DimImg mergeSort(E *dst, const std::vector<E *> &tab, const std::vector<DimImg> &tabSize, const WeightFunct &weightFunct) {
|
||||
DimImg count = 0;
|
||||
std::vector<DimImg> curIdx (tab.size (), 0);
|
||||
for (;;) {
|
||||
int minIdx = -1;
|
||||
WeightT minLevel = 0;
|
||||
for (DimImg i = 0; i < curIdx.size (); ++i) {
|
||||
if (curIdx[i] >= tabSize[i])
|
||||
continue;
|
||||
if (minIdx >= 0 &&
|
||||
!weightFunct.isWeightInf (tab[i][curIdx[i]], minLevel))
|
||||
continue;
|
||||
minIdx = i;
|
||||
minLevel = tab[i][curIdx[i]];
|
||||
// LOG ("set minIdx:" << minIdx << " minLevel:" << minLevel);
|
||||
}
|
||||
if (minIdx < 0)
|
||||
break;
|
||||
*dst++ = tab[minIdx][curIdx[minIdx]++];
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
} // otb
|
96
src/QuadTree/QuadTreeBuilder.cpp
Normal file
96
src/QuadTree/QuadTreeBuilder.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "QuadTree/QuadTreeBuilder.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
void
|
||||
QuadTreeBuilder::buildTree(Tree &tree) {
|
||||
|
||||
// Building the tree by setting leafs's and components's parents
|
||||
tree.resize((DimImg)width, (DimImg)height);
|
||||
updateAttributes(tree);
|
||||
DimImg parentCount = getStepCount(0, 0, width, height);
|
||||
|
||||
DimImg parentUsed = parentCount;
|
||||
|
||||
// We set the root
|
||||
compParents[parentCount-1] = parentCount;
|
||||
tree.setNodeCount(parentCount);
|
||||
|
||||
setParents(parentCount, 0, 0, width, height, width, height);
|
||||
|
||||
// Building children array
|
||||
|
||||
std::partial_sum(childCount, childCount+parentUsed+2, childCount);
|
||||
|
||||
for (DimNodeId i = 0; i < tree.getLeafCount(); ++i) {
|
||||
DimNodeId idP = leafParents[i];
|
||||
children[childCount[idP+1]++] = i;
|
||||
}
|
||||
|
||||
for (DimNodeId i = tree.getLeafCount(); i < tree.getLeafCount()+parentUsed-1; ++i) {
|
||||
DimNodeId idP = compParents[i-tree.getLeafCount()];
|
||||
children[childCount[idP+1]++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
DimImg
|
||||
QuadTreeBuilder::getStepCount(const DimSideImg &x, const DimSideImg &y, const DimSideImg &w, const DimSideImg &h) const {
|
||||
|
||||
DimImg nbSteps = 1;
|
||||
|
||||
if (w > 2 && h > 2) {
|
||||
DimSideImg dw1 = w >> 1;
|
||||
DimSideImg dh1 = h >> 1;
|
||||
DimSideImg dw2 = (w >> 1) + (w & 1);
|
||||
DimSideImg dh2 = (h >> 1) + (h & 1);
|
||||
|
||||
DimSideImg coords [4][4] = {
|
||||
{x , y , dw1, dh1},
|
||||
{x + dw1, y , dw2, dh1},
|
||||
{x , y + dh1, dw1, dh2},
|
||||
{x + dw1, y + dh1, dw2, dh2}
|
||||
};
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
nbSteps += getStepCount(coords[i][0], coords[i][1], coords[i][2], coords[i][3]);
|
||||
}
|
||||
|
||||
return nbSteps;
|
||||
}
|
||||
|
||||
DimImg
|
||||
QuadTreeBuilder::setParents(DimImg &parentId,
|
||||
const DimSideImg &x, const DimSideImg &y, const DimSideImg &w, const DimSideImg &h,
|
||||
const DimSideImg &imgW, const DimSideImg &imgH, DimImg level) const {
|
||||
|
||||
DEF_LOG("setParents", "parentId: " << parentId << " x: " << x << " y: " << y << " w: " << w << " h: " << h);
|
||||
DimImg localId = --parentId;
|
||||
|
||||
if (w > 2 && h > 2) {
|
||||
DimSideImg dw1 = w >> 1;
|
||||
DimSideImg dh1 = h >> 1;
|
||||
DimSideImg dw2 = (w >> 1) + (w & 1);
|
||||
DimSideImg dh2 = (h >> 1) + (h & 1);
|
||||
|
||||
DimSideImg coords [4][4] = {
|
||||
{x , y , dw1, dh1},
|
||||
{x + dw1, y , dw2, dh1},
|
||||
{x , y + dh1, dw1, dh2},
|
||||
{x + dw1, y + dh1, dw2, dh2}
|
||||
};
|
||||
|
||||
childCount[localId+2] = 4;
|
||||
for (int i = 0; i < 4; i++)
|
||||
compParents[setParents(parentId, coords[i][0], coords[i][1], coords[i][2], coords[i][3], imgW, imgH, level+1)] = localId;
|
||||
} else
|
||||
for (DimSideImg i = x; i < w + x; i++)
|
||||
for (DimSideImg j = y; j < h + y; j++) {
|
||||
DimSideImg id = i + j * imgW;
|
||||
leafParents[id] = localId;
|
||||
childCount[localId+2]++;
|
||||
}
|
||||
|
||||
return localId;
|
||||
}
|
||||
|
||||
};
|
112
src/Tree.cpp
Normal file
112
src/Tree.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include "Tree.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
Tree::Tree(const DimImg &leafC, const DimSideImg &width, const DimSideImg &height)
|
||||
: size(width, height),
|
||||
leafCount(leafC),
|
||||
nodeCount(leafCount),
|
||||
leafParents(nullptr),
|
||||
compParents(nullptr),
|
||||
children(nullptr),
|
||||
childCount(nullptr),
|
||||
newCompIndex(nullptr),
|
||||
state(State::Void)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
Tree::Tree(const DimSideImg &width, const DimSideImg &height)
|
||||
: Tree(width * height, width, height)
|
||||
{}
|
||||
|
||||
Tree::Tree(const DimSideImg &leafC)
|
||||
: Tree(leafC, 0, 0)
|
||||
{}
|
||||
|
||||
Tree::~Tree() { reset(); }
|
||||
|
||||
void
|
||||
Tree::resize(const DimImg &newLeafCount, const DimSideImg &w, const DimSideImg &h) {
|
||||
leafCount = newLeafCount;
|
||||
nodeCount = 0;
|
||||
size = Size(w, h);
|
||||
init();
|
||||
}
|
||||
|
||||
void
|
||||
Tree::resize(const DimSideImg &w, const DimSideImg &h) { resize((DimImg)w * (DimImg)h, w, h); }
|
||||
|
||||
void
|
||||
Tree::resize(const DimImg &newLeafCount) { resize(newLeafCount, 0, 0); }
|
||||
|
||||
void
|
||||
Tree::init() {
|
||||
reset();
|
||||
book();
|
||||
state = State::Initialized;
|
||||
}
|
||||
|
||||
void
|
||||
Tree::reset() {
|
||||
delete[] leafParents;
|
||||
leafParents = compParents = nullptr;
|
||||
|
||||
delete[] children;
|
||||
|
||||
delete[] childCount;
|
||||
children = childCount = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Tree::book() {
|
||||
if (!leafCount)
|
||||
return;
|
||||
|
||||
leafParents = new DimNodeId[leafCount*2];
|
||||
compParents = leafParents + leafCount;
|
||||
|
||||
std::fill_n(leafParents, leafCount*2, leafCount*2);
|
||||
|
||||
children = new DimNodeId[(leafCount-1)*2];
|
||||
childCount = new DimNodeId[leafCount+2];
|
||||
|
||||
std::fill_n(children, (leafCount-1)*2, leafCount*2);
|
||||
std::fill_n(childCount, leafCount+2, 0);
|
||||
}
|
||||
|
||||
template<typename FuncToApply>
|
||||
void
|
||||
Tree::forEachChild(const DimNodeId &idx, const FuncToApply& f) {
|
||||
std::vector<DimNodeId> childrenNode = getChildren(idx);
|
||||
|
||||
for(DimNodeId i = 0; i < childrenNode.size(); ++i)
|
||||
f(childrenNode[i]);
|
||||
}
|
||||
|
||||
std::vector<DimNodeId>
|
||||
Tree::getChildren(const DimNodeId &idx) const {
|
||||
std::vector<DimNodeId> childrenRet;
|
||||
|
||||
for (DimNodeId i = childCount[idx]; i < childCount[idx+1]; ++i)
|
||||
childrenRet.push_back(children[i]);
|
||||
|
||||
return childrenRet;
|
||||
}
|
||||
|
||||
#ifdef SMART_LOG
|
||||
inline void
|
||||
Tree::printTree(const Size &size, const bool &rec) {
|
||||
std::cout << "tree level parent " << (rec ? "countRec" : "count") << std::endl;
|
||||
Size doubleSize (size.width, 2*size.height);
|
||||
printMap(std::cout, leafParents, doubleSize) << std::endl;
|
||||
}
|
||||
|
||||
inline void
|
||||
Tree::printNewCompIndex (const Size &size) {
|
||||
std::cout << "newCompIndex" << std::endl;
|
||||
printMap (std::cout, newCompIndex, size) << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // Obelix
|
338
src/TreeOfShapesGeraud/ToSBuilder.cpp
Normal file
338
src/TreeOfShapesGeraud/ToSBuilder.cpp
Normal file
@ -0,0 +1,338 @@
|
||||
#include "TreeOfShapesGeraud/ToSBuilder.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/features2d/features2d.hpp>
|
||||
|
||||
namespace otb {
|
||||
|
||||
ToSBuilder::ToSBuilder(const std::string &imageName)
|
||||
: imagePath(imageName)
|
||||
{}
|
||||
|
||||
void
|
||||
ToSBuilder::buildTree(Tree& tree) {
|
||||
std::cout << "ToS::buildTree: imagePath = " << imagePath << std::endl;
|
||||
|
||||
cv::Mat img = cv::imread(imagePath, CV_LOAD_IMAGE_GRAYSCALE);
|
||||
|
||||
std::vector<std::vector<std::pair<uchar, uchar>>> intImg;
|
||||
|
||||
cv::Mat ub;
|
||||
std::vector <pxCoord> sorted;
|
||||
std::vector <std::vector <pxCoord> > parentInt(((img.cols+2)<<2)-1, std::vector<pxCoord> (((img.rows+2)<<2)-1));
|
||||
std::vector <std::vector <pxCoord> > parent;
|
||||
|
||||
|
||||
interpolateImg(img, intImg);
|
||||
sortImgElemsToS(intImg, sorted, ub);
|
||||
treeCore(sorted, regular, parentInt);
|
||||
canonizeTree(sorted, parentInt, ub);
|
||||
unInterpolateParent(parentInt, ub, parent);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ToSBuilder::interpolateImg(const cv::Mat &imgTrue, std::vector <std::vector <std::pair<uchar, uchar> > > &iimg) const {
|
||||
|
||||
// Taille de l'image *4 (Khalimsky grid)
|
||||
int iimgMRows = ((imgTrue.cols+2)<<2)-1;
|
||||
int iimgMCols = ((imgTrue.rows+2)<<2)-1;
|
||||
|
||||
iimg.clear();
|
||||
iimg.resize(iimgMRows, std::vector <std::pair<uchar, uchar> > (iimgMCols, std::pair<uchar,uchar>(0,0)));
|
||||
|
||||
|
||||
// Calcul de la mediane (récupération de la ligne 0 et de la ligne size-1)
|
||||
std::vector <uchar> values; // median
|
||||
for (int i=0; i < imgTrue.cols; ++i){
|
||||
values.push_back(imgTrue.at<uchar>(0,i));
|
||||
values.push_back(imgTrue.at<uchar>(imgTrue.rows-1,i));
|
||||
}
|
||||
|
||||
// Calcul de la mediane (récupération de la colonne 0 et de la colonne size-1)
|
||||
for (int i = 1; i < imgTrue.rows-1; ++i){
|
||||
values.push_back(imgTrue.at<uchar>(i,0));
|
||||
values.push_back(imgTrue.at<uchar>(i,imgTrue.cols-1));
|
||||
}
|
||||
|
||||
// Calcul de la médiane
|
||||
std::sort(values.begin(), values.end()); // determine the median of the surrounding elems
|
||||
uchar median = values[values.size()/2];
|
||||
|
||||
|
||||
// === Interpolation ===
|
||||
|
||||
// Remplissage de la seconde et de la première ligne, égales à la médiane (cf. article)
|
||||
for (int col = 1; col < iimgMCols; col+=2){
|
||||
iimg[1][col].lower = iimg[1][col].upper =
|
||||
iimg[iimgMRows-2][col].lower = iimg[iimgMRows-2][col].upper = median;
|
||||
}
|
||||
|
||||
for (int row = 1; row < iimgMRows; row+=2){
|
||||
iimg[row][1].lower = iimg[row][1].upper =
|
||||
iimg[row][iimgMCols-2].lower = iimg[row][iimgMCols-2].upper = median;
|
||||
}
|
||||
|
||||
// Remplissage de tous les pixels correspondants à l'image initiale
|
||||
const uchar *p = NULL;
|
||||
for(int row = 1, szrow = imgTrue.rows+2; row < szrow; ++row) {
|
||||
if (row < imgTrue.rows+1)
|
||||
p = imgTrue.ptr(row-1);
|
||||
|
||||
for(int col = 1, szcol = imgTrue.cols+2; col < szcol; ++col) {
|
||||
if (row < imgTrue.rows+1 && col < imgTrue.cols+1)
|
||||
iimg[(col<<2)+1][(row<<2)+1].lower = iimg[(col<<2)+1][(row<<2)+1].upper = *p++;
|
||||
|
||||
iimg[(col<<2)+1-2][(row<<2)+1].lower = iimg[(col<<2)+1-2][(row<<2)+1].upper =
|
||||
std::max(iimg[(col<<2)+1][(row<<2)+1].lower, iimg[(col<<2)+1-4][(row<<2)+1].lower);
|
||||
|
||||
iimg[(col<<2)+1][(row<<2)+1-2].lower = iimg[(col<<2)+1][(row<<2)+1-2].upper =
|
||||
std::max(iimg[(col<<2)+1][(row<<2)+1].lower, iimg[(col<<2)+1][(row<<2)+1-4].lower);
|
||||
}
|
||||
}
|
||||
|
||||
// Remplissage de toutes les cases intermédiaires entre les pixels
|
||||
for (int irow = 3, szir = iimgMCols; irow < szir; irow+=4) {
|
||||
for (int icol = 3, szic = iimgMRows; icol < szic; icol+=4) {
|
||||
|
||||
iimg[icol][irow].lower = iimg[icol][irow].upper =
|
||||
std::max(iimg[icol-2][irow].lower, iimg[icol+2][irow].lower);
|
||||
//equivalent:
|
||||
//iimg[icol][irow].lower = iimg[icol][irow].upper =
|
||||
// std::max(iimg[icol][irow-2].lower, iimg[icol][irow+2].lower);
|
||||
}
|
||||
}
|
||||
|
||||
// Remplissage des cases entre les cases intermédiaires et les pixels (verticalement)
|
||||
for (int irow=0, szir = iimgMCols; irow < szir; irow+=2) {
|
||||
for (int icol=1, szic = iimgMRows; icol < szic; icol+=2) {
|
||||
|
||||
if (irow && irow != szir-1) {
|
||||
iimg[icol][irow].lower = std::min(iimg[icol][irow-1].lower, iimg[icol][irow+1].lower);
|
||||
iimg[icol][irow].upper = std::max(iimg[icol][irow-1].upper, iimg[icol][irow+1].upper);
|
||||
} else if (!irow) {
|
||||
iimg[icol][irow].lower = iimg[icol][irow].upper = iimg[icol][irow+1].lower;
|
||||
} else {
|
||||
iimg[icol][irow].lower = iimg[icol][irow].upper = iimg[icol][irow-1].lower;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remplissage des cases entre les cases intermédiaires et les pixels (verticalement)
|
||||
for (int irow=1, szir = iimgMCols; irow < szir; irow+=2) {
|
||||
for (int icol=0, szic = iimgMRows; icol < szic; icol+=2) {
|
||||
|
||||
if (icol && icol != szic-1) {
|
||||
iimg[icol][irow].lower = std::min(iimg[icol-1][irow].lower, iimg[icol+1][irow].lower);
|
||||
iimg[icol][irow].upper = std::max(iimg[icol-1][irow].upper, iimg[icol+1][irow].upper);
|
||||
} else if (!icol) {
|
||||
iimg[icol][irow].lower = iimg[icol][irow].upper = iimg[icol+1][irow].lower;
|
||||
} else {
|
||||
iimg[icol][irow].lower = iimg[icol][irow].upper = iimg[icol-1][irow].lower;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remplissage de toutes les cases en diagonales des pixels
|
||||
for (int irow=0, szir = iimgMCols; irow < szir; irow+=2) {
|
||||
for (int icol=0, szic = iimgMRows; icol < szic; icol+=2) {
|
||||
|
||||
if (irow && irow != szir-1){
|
||||
iimg[icol][irow].lower = std::min(iimg[icol][irow-1].lower, iimg[icol][irow+1].lower);
|
||||
iimg[icol][irow].upper = std::max(iimg[icol][irow-1].upper, iimg[icol][irow+1].upper);
|
||||
} else if (!irow){
|
||||
iimg[icol][irow].lower = iimg[icol][irow+1].lower;
|
||||
iimg[icol][irow].upper = iimg[icol][irow+1].upper;
|
||||
} else{
|
||||
iimg[icol][irow].lower = iimg[icol][irow-1].lower;
|
||||
iimg[icol][irow].upper = iimg[icol][irow-1].upper;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pxCoord
|
||||
ToSBuilder::specialPop(std::vector <std::vector <pxCoord> > &q, int &qElems, const uchar &lo, uchar &level) const {
|
||||
pxCoord rValue;
|
||||
|
||||
if (!qElems)
|
||||
return rValue;
|
||||
for (int i=0; ; ++i) {
|
||||
|
||||
if ((level-lo+i) < (int)q.size() && !q[level-lo+i].empty()) {
|
||||
rValue = q[level-lo+i].back();
|
||||
q[level-lo+i].pop_back(); --qElems;
|
||||
level+=i;
|
||||
break;
|
||||
} else if (i && (level-lo-i) >= 0 && !q[level-lo-i].empty()) {
|
||||
rValue = q[level-lo-i].back();
|
||||
q[level-lo-i].pop_back(); --qElems;
|
||||
level-=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rValue;
|
||||
}
|
||||
|
||||
void
|
||||
ToSBuilder::specialPush(std::vector <std::vector <pxCoord> > &q, int &qElems, const uchar &lo, const uchar &level,
|
||||
const pxCoord &coord, const std::pair<uchar, uchar> &bounds) const {
|
||||
int pLevel;
|
||||
if (bounds.first > level)
|
||||
pLevel = bounds.first;
|
||||
else if (bounds.second < level)
|
||||
pLevel = bounds.second;
|
||||
else
|
||||
pLevel = level;
|
||||
q[pLevel-lo].push_back(coord); ++qElems;
|
||||
}
|
||||
|
||||
void
|
||||
ToSBuilder::sortImgElemsToS(const std::vector <std::vector <std::pair <uchar, uchar> > > &iimg,
|
||||
std::vector <pxCoord> &order, cv::Mat &eimg) const {
|
||||
|
||||
order.clear();
|
||||
std::vector <std::vector <bool> > seen(iimg.size(), std::vector <bool> (iimg.back().size(), false));
|
||||
eimg.create(iimg.back().size(), iimg.size(), CV_8U);
|
||||
|
||||
|
||||
CompareByX cbf = CompareByX();
|
||||
CompareByY cbs = CompareByY();
|
||||
uchar lo = std::min_element(iimg[0].begin(), iimg[0].end(), cbs)->first;
|
||||
uchar hi = std::max_element(iimg[0].begin(), iimg[0].end(), cbs)->second;
|
||||
|
||||
for (int i=1, szi = iimg.size(); i < szi; ++i){
|
||||
lo = std::min(lo, std::min_element(iimg[i].begin(), iimg[i].end(), cbf)->first);
|
||||
hi = std::max(hi, std::max_element(iimg[i].begin(), iimg[i].end(), cbs)->second);
|
||||
}
|
||||
|
||||
std::vector <std::vector <pxCoord> > q (hi-lo+1,(std::vector<pxCoord>()));
|
||||
int qElems = 0;
|
||||
|
||||
q[iimg[0][0].lower - lo].push_back(std::make_pair(0,0)); ++qElems;
|
||||
seen[0][0] = true;
|
||||
uchar level = iimg[0][0].first;
|
||||
|
||||
for (; qElems; ){
|
||||
pxCoord cur = specialPop(q, qElems, lo, level);
|
||||
eimg.at<uchar>(cur.Y, cur.X) = level;
|
||||
order.push_back(cur);
|
||||
|
||||
pxDirected curDir = make_pxDirected(cur, 1, regular);
|
||||
for (pxCoord ngb = nextCoord(curDir); ; ngb = nextCoord(curDir)){
|
||||
if (!coordOk(ngb, iimg.size(), iimg.back().size()) || seen[ngb.X][ngb.Y]){
|
||||
if (nextDir(curDir))
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
seen[ngb.X][ngb.Y] = true;
|
||||
specialPush(q, qElems, lo, level, ngb, iimg[ngb.X][ngb.Y]);
|
||||
if (!nextDir(curDir))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ToSBuilder::unInterpolateParent(std::vector<std::vector <pxCoord> > parentOld, const cv::Mat &ub,
|
||||
std::vector<std::vector <pxCoord> > &parentNew) const {
|
||||
|
||||
const pxCoord dummy = make_pxCoord(-1,-1);
|
||||
std::vector <std::vector<pxCoord> > repCanon(parentOld.size(), std::vector<pxCoord>(parentOld[0].size(), make_pxCoord(-1,-1)));
|
||||
|
||||
const int oX = ((parentOld.size()+1)>>2)-2;
|
||||
const int oY = ((parentOld[0].size()+1)>>2)-2;
|
||||
|
||||
parentNew.clear();
|
||||
parentNew.resize(oX, std::vector<pxCoord>(oY));
|
||||
|
||||
for (int i=5, szi = parentOld.size()-5; i < szi; i+=4){ // setting the replacement canons
|
||||
for (int j=5, szj = parentOld[i].size()-5; j < szj; j+=4){
|
||||
if (ub.at<uchar>(j,i) != ub.at<uchar>(parentOld[i][j].Y, parentOld[i][j].X) || // canon element
|
||||
parentOld[i][j] == make_pxCoord(i,j)){ // tree root
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isKhalimskyOriginalPixel(parentOld[i][j], oX, oY) &&
|
||||
repCanon[parentOld[i][j].X][parentOld[i][j].Y] == dummy){
|
||||
repCanon[parentOld[i][j].X][parentOld[i][j].Y] = make_pxCoord(i,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=5; i < ((oX<<2) + 5); i+=4){
|
||||
for (int j=5; j < ((oY<<2) + 5); j+=4){
|
||||
const pxCoord &pold = parentOld[i][j];
|
||||
pxCoord &pnew = parentNew[(i-5)>>2][(j-5)>>2];
|
||||
if (repCanon[pold.X][pold.Y] == dummy){ // no replacement
|
||||
pnew = make_pxCoord((pold.X-5)>>2, (pold.Y-5)>>2);
|
||||
}
|
||||
else if (repCanon[pold.X][pold.Y] == make_pxCoord(i,j)){ // if current is becoming canon
|
||||
const pxCoord ppold = parentOld[pold.X][pold.Y];
|
||||
if (repCanon[ppold.X][ppold.Y] == dummy) // point to what the old canon was pointing to
|
||||
pnew = make_pxCoord((ppold.X-5)>>2, (ppold.Y-5)>>2);
|
||||
else // ba careful if that also got replacement
|
||||
pnew = make_pxCoord((repCanon[ppold.X][ppold.Y].X-5)>>2,(repCanon[ppold.X][ppold.Y].Y-5)>>2);
|
||||
}
|
||||
else
|
||||
pnew = make_pxCoord((repCanon[pold.X][pold.Y].X-5)>>2, (repCanon[pold.X][pold.Y].Y-5)>>2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pxCoord
|
||||
ToSBuilder::findRoot(const pxCoord &px, std::vector<std::vector<pxCoord> > &zpar) const {
|
||||
if (zpar[px.X][px.Y] != px)
|
||||
zpar[px.X][px.Y] = findRoot(zpar[px.X][px.Y], zpar);
|
||||
return zpar[px.X][px.Y];
|
||||
}
|
||||
|
||||
void
|
||||
ToSBuilder::treeCore(const std::vector<pxCoord> &sorted, pxType curType, std::vector<std::vector<pxCoord> > &parent) const {
|
||||
std::vector <std::vector<pxCoord> > zpar(parent.size(), std::vector<pxCoord>(parent.back().size(), make_pxCoord(-1,-1)));
|
||||
//for (int i=0, szi = sorted.size(); i < szi; ++i){
|
||||
for (int i=sorted.size()-1; i >=0; --i){
|
||||
const pxCoord &cur = sorted[i];
|
||||
parent[cur.X][cur.Y] = zpar[cur.X][cur.Y] = cur;
|
||||
pxDirected curDir = make_pxDirected(cur, 1, curType);
|
||||
for (; nextDir(curDir); ){
|
||||
pxCoord n = nextCoord(curDir);
|
||||
if (!coordOk(n, parent.size(), parent.back().size()) || zpar[n.X][n.Y] == make_pxCoord(-1,-1))
|
||||
continue;
|
||||
pxCoord root = findRoot(n, zpar);
|
||||
if (root != cur){
|
||||
parent[root.X][root.Y] = zpar[root.X][root.Y] = cur;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ToSBuilder::canonizeTree(const std::vector<pxCoord> &sorted, std::vector<std::vector<pxCoord> > &parent, const cv::Mat &img) const {
|
||||
//for (int i=sorted.size()-1; i >=0; --i){
|
||||
for (int i=0, szi = sorted.size(); i < szi; ++i){
|
||||
const pxCoord &p = sorted[i];
|
||||
const pxCoord &q = parent[p.X][p.Y];
|
||||
if (getCvMatElem(img, parent[q.X][q.Y]) == getCvMatElem(img, q))
|
||||
parent[p.X][p.Y] = parent[q.X][q.Y];
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ToSBuilder::isKhalimskyOriginalPixel(const pxCoord &kpx, const int oX, const int oY) const {
|
||||
if ((kpx.X - 5)%4 || (kpx.Y - 5)%4)
|
||||
return false;
|
||||
if ((kpx.X-5)>>2 < 0 || (kpx.X-5)>>2 >= oX)
|
||||
return false;
|
||||
if ((kpx.Y-5)>>2 < 0 || (kpx.Y-5)>>2 >= oY)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // otb
|
121
src/TreeOfShapesGeraud/ToSutils.cpp
Normal file
121
src/TreeOfShapesGeraud/ToSutils.cpp
Normal file
@ -0,0 +1,121 @@
|
||||
#include "TreeOfShapesGeraud/ToSutils.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
// XXX
|
||||
|
||||
bool
|
||||
CompareByX::operator()(const pxCoord &lhs, const pxCoord &rhs) { return lhs.X < rhs.X; }
|
||||
|
||||
bool
|
||||
CompareByY::operator()(const pxCoord &lhs, const pxCoord &rhs) { return lhs.Y < rhs.Y; }
|
||||
|
||||
pxCoord
|
||||
nextCoord (pxDirected &dpx){
|
||||
pxCoord rValue = dpx.coord;
|
||||
if (dpx.pxtype == regular){
|
||||
if (dpx.pxdir <= 1){
|
||||
--rValue.X;
|
||||
}
|
||||
else if (dpx.pxdir <= 2){
|
||||
++rValue.Y;
|
||||
}
|
||||
else if (dpx.pxdir <= 4){
|
||||
++rValue.X;
|
||||
}
|
||||
else if (dpx.pxdir <= 8){
|
||||
--rValue.Y;
|
||||
}
|
||||
}
|
||||
else if (dpx.pxtype == dual){
|
||||
|
||||
if (! ((dpx.coord.X %2)-(dpx.coord.Y%2)) ) // (odd,odd) or (even,even) -- error
|
||||
return dpx.coord;
|
||||
else if (dpx.coord.X % 2){ // (odd,even) -> vertical
|
||||
if (dpx.pxdir <= 1<<0){
|
||||
rValue.X -= 2;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<1){
|
||||
--rValue.X; ++rValue.Y;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<2){
|
||||
++rValue.X; ++rValue.Y;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<3){
|
||||
rValue.X += 2;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<4){
|
||||
++rValue.X; --rValue.Y;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<5){
|
||||
--rValue.X; --rValue.Y;
|
||||
}
|
||||
}
|
||||
else { // (even,odd) -> horizontal
|
||||
if (dpx.pxdir <= 1<<0){
|
||||
--rValue.X; ++rValue.Y;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<1){
|
||||
rValue.Y += 2;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<2){
|
||||
++rValue.X; ++rValue.Y;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<3){
|
||||
++rValue.X; --rValue.Y;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<4){
|
||||
rValue.Y -= 2;
|
||||
}
|
||||
else if (dpx.pxdir <= 1<<5){
|
||||
--rValue.X; --rValue.Y;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dpx.pxdir < 1) dpx.pxdir = 2;
|
||||
else dpx.pxdir <<= 1;
|
||||
return rValue;
|
||||
|
||||
}
|
||||
|
||||
bool
|
||||
coordOk (const pxCoord &coord, int imgCols, int imgRows){
|
||||
if (coord.X < 0 || coord.Y < 0)
|
||||
return false;
|
||||
if (coord.X >= imgCols || coord.Y >= imgRows)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nextDir(const pxDirected &dpx){
|
||||
if (dpx.pxtype == regular)
|
||||
return (dpx.pxdir <= 1<<3);
|
||||
else if (dpx.pxtype == dual)
|
||||
return (dpx.pxdir <= 1<<5);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
double
|
||||
getCvMatElem(const cv::Mat &img, const std::pair<int, int> &coord){
|
||||
return getCvMatElem(img, coord.first, coord.second);
|
||||
}
|
||||
|
||||
double
|
||||
getCvMatElem(const cv::Mat &img, int X, int Y){
|
||||
if (img.type() == CV_8U)
|
||||
return img.at<uchar>(Y, X);
|
||||
else if (img.type() == CV_32S)
|
||||
return img.at<int32_t>(Y, X);
|
||||
else if (img.type() == CV_32F)
|
||||
return img.at<float>(Y, X);
|
||||
else if (img.type() == CV_16S)
|
||||
return img.at<short>(Y, X);
|
||||
else if (img.type() == CV_16U)
|
||||
return img.at<unsigned short>(Y, X);
|
||||
|
||||
return img.at<uchar>(Y, X);
|
||||
}
|
||||
|
||||
} // otb
|
115
src/XMLTree/XMLTreeBuilder.cpp
Normal file
115
src/XMLTree/XMLTreeBuilder.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include "XMLTree/XMLTreeBuilder.hpp"
|
||||
|
||||
namespace otb {
|
||||
|
||||
void
|
||||
XMLTreeBuilder::buildTree(Tree &tree) {
|
||||
TiXmlDocument doc(fileName.c_str());
|
||||
|
||||
if (!doc.LoadFile())
|
||||
return;
|
||||
|
||||
const TiXmlElement *treeNode = doc.FirstChild("Tree")->ToElement();
|
||||
|
||||
int width, height;
|
||||
|
||||
if (treeNode->QueryIntAttribute("width", &width) == TIXML_SUCCESS &&
|
||||
treeNode->QueryIntAttribute("height", &height) == TIXML_SUCCESS)
|
||||
tree.resize(width, height);
|
||||
else {
|
||||
if (treeNode->QueryIntAttribute("leafCount", &width) != TIXML_SUCCESS)
|
||||
return;
|
||||
tree.resize(width);
|
||||
}
|
||||
|
||||
DimNodeId nodeCount = getNodeCount(treeNode);
|
||||
tree.setNodeCount(nodeCount);
|
||||
|
||||
updateAttributes(tree);
|
||||
|
||||
DimNodeId rootParent = nodeCount;
|
||||
compParents[--rootParent] = nodeCount;
|
||||
readNodeChildren(treeNode->FirstChild()->ToElement(), rootParent);
|
||||
|
||||
std::partial_sum(childCount, childCount+nodeCount+2, childCount);
|
||||
|
||||
for (DimNodeId i = 0; i < tree.getLeafCount(); ++i) {
|
||||
DimNodeId idP = leafParents[i];
|
||||
children[childCount[idP+1]++] = i;
|
||||
}
|
||||
|
||||
for (DimNodeId i = tree.getLeafCount(); i < tree.getLeafCount()+nodeCount-1; ++i) {
|
||||
DimNodeId idP = compParents[i-tree.getLeafCount()];
|
||||
children[childCount[idP+1]++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
DimNodeId
|
||||
XMLTreeBuilder::getNodeCount(const TiXmlElement *node) {
|
||||
DimNodeId nodeCount = 0;
|
||||
|
||||
for(const TiXmlNode *child = node->FirstChild("Node"); child; child = child->NextSibling("Node")) {
|
||||
nodeCount++;
|
||||
nodeCount += getNodeCount(child->ToElement());
|
||||
}
|
||||
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
void
|
||||
XMLTreeBuilder::readNodeChildren(const TiXmlElement *node, DimNodeId &id) {
|
||||
|
||||
DimNodeId idP = id;
|
||||
for(const TiXmlNode *child = node->FirstChild(); child; child = child->NextSibling()) {
|
||||
if (std::string(child->Value()) == "Node") {
|
||||
compParents[--id] = idP;
|
||||
std::cout << id << std::endl;
|
||||
readNodeChildren(child->ToElement(), id);
|
||||
childCount[idP+2]++;
|
||||
} else if (child->Value() == std::string("Leaf")) {
|
||||
int leafId;
|
||||
child->ToElement()->QueryIntAttribute("id", &leafId);
|
||||
leafParents[leafId] = idP;
|
||||
childCount[idP+2]++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
XMLTreeBuilder::exportToFile(const Tree &tree, const std::string &fileName) {
|
||||
TiXmlDocument doc;
|
||||
TiXmlDeclaration *decl = new TiXmlDeclaration( "1.0", "", "" );
|
||||
doc.LinkEndChild(decl);
|
||||
|
||||
TiXmlElement *treeNode = new TiXmlElement("Tree");
|
||||
doc.LinkEndChild(treeNode);
|
||||
treeNode->SetAttribute("leafCount", tree.getLeafCount());
|
||||
|
||||
if (tree.getSize().width != 0)
|
||||
treeNode->SetAttribute("width", tree.getSize().width);
|
||||
|
||||
if (tree.getSize().height != 0)
|
||||
treeNode->SetAttribute("height", tree.getSize().height);
|
||||
|
||||
// Construct the tree
|
||||
writeNodeChildren(tree, tree.getAbsRoot(), treeNode);
|
||||
|
||||
doc.SaveFile(fileName.c_str());
|
||||
}
|
||||
|
||||
void
|
||||
XMLTreeBuilder::writeNodeChildren(const Tree &tree, const DimNodeId &idx, TiXmlElement *node) {
|
||||
if (idx < tree.getLeafCount()) {
|
||||
TiXmlElement *leafNode = new TiXmlElement("Leaf");
|
||||
node->LinkEndChild(leafNode);
|
||||
leafNode->SetAttribute("id", idx);
|
||||
} else {
|
||||
TiXmlElement *nodeNode = new TiXmlElement("Node");
|
||||
node->LinkEndChild(nodeNode);
|
||||
|
||||
for (int id : tree.getChildren(idx - tree.getLeafCount()))
|
||||
writeNodeChildren(tree, id, nodeNode);
|
||||
}
|
||||
}
|
||||
} // otb
|
7
src/debug.cpp
Normal file
7
src/debug.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include "debug.hpp"
|
||||
|
||||
|
||||
using namespace utils;
|
||||
|
||||
unsigned int
|
||||
Log::indent = 0;
|
24
src/testMain.cpp
Normal file
24
src/testMain.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include <iostream>
|
||||
|
||||
#define SMART_LOG
|
||||
|
||||
#include "Tree.hpp"
|
||||
#include "baseDef.hpp"
|
||||
#include "BuildTree.hpp"
|
||||
#include "QuadTree/QuadTreeBuilder.hpp"
|
||||
#include "XMLTree/XMLTreeBuilder.hpp"
|
||||
#include "DAPTree/DAPTreeBuilder.hpp"
|
||||
#include "ImageInterface.hpp"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
otb::ImageInterface<uint32_t> imgInt("test.png");
|
||||
imgInt.readImage();
|
||||
|
||||
std::cout << "Value of 0: " << imgInt.getValue(0) << std::endl;
|
||||
|
||||
otb::Tree tree;
|
||||
//otb::BuildTree::buildTree(tree, otb::DAPTreeBuilder());
|
||||
|
||||
return 0;
|
||||
}
|
8
tests/ToSGeraudCoord.txt
Normal file
8
tests/ToSGeraudCoord.txt
Normal file
@ -0,0 +1,8 @@
|
||||
std::vector of length 6, capacity 6 = {
|
||||
|
||||
std::vector of length 6, capacity 6 = {{1434420080, 21845}, {0, 3}, {0, 1}, {1, 2}, {2, 2}, {3, 2}},
|
||||
std::vector of length 6, capacity 6 = {{1434462560, 21845}, {1, 3}, {0, 0}, {1, 0}, {2, 0}, {3, 1}},
|
||||
std::vector of length 6, capacity 6 = {{1434460240, 21845}, {1, 4}, {2, 3}, {1, 4}, {0, 5}, {3, 0}},
|
||||
std::vector of length 6, capacity 6 = {{1434459968, 21845}, {2, 5}, {1, 5}, {1, 5}, {2, 5}, {4, 3}},
|
||||
std::vector of length 6, capacity 6 = {{1434461456, 21845}, {3, 5}, {3, 0}, {4, 2}, {4, 1}, {4, 4}},
|
||||
std::vector of length 6, capacity 6 = {{1434460032, 21845}, {5, 2}, {5, 3}, {4, 0}, {5, 3}, {5, 3}}}
|
BIN
tests/ToSGeraudIdx.ods
Normal file
BIN
tests/ToSGeraudIdx.ods
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user