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:
Git Merciol 2017-10-21 11:53:45 +02:00
parent 98823f5f30
commit bc00fd7cbc
42 changed files with 3620 additions and 0 deletions

32
CMakeLists.txt Normal file
View 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
View 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
View 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
View 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

View 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
View 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

View 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

View 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 &image;
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

View 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

View 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

View 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
View 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

View 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
View 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

View 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

View 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

View 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
View 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

View 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

View 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

View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1 @@
otb_module(TreeBuilder DEPENDS OTBTinyXML OTBOpenCV DESCRIPTION "A description string")

28
src/Attribute.cpp Normal file
View 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

View 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
View 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
View 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
View 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

View 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
View 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

View 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
View 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

View 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

View 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

View 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
View File

@ -0,0 +1,7 @@
#include "debug.hpp"
using namespace utils;
unsigned int
Log::indent = 0;

24
src/testMain.cpp Normal file
View 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
View 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

Binary file not shown.