src/qvip/qvimagefeatures/qvcomponenttree.cpp

Go to the documentation of this file.
00001 /*
00002  *      Copyright (C) 2007. PARP Research Group.
00003  *      <http://perception.inf.um.es>
00004  *      University of Murcia, Spain.
00005  *
00006  *      This file is part of the QVision library.
00007  *
00008  *      QVision is free software: you can redistribute it and/or modify
00009  *      it under the terms of the GNU Lesser General Public License as
00010  *      published by the Free Software Foundation, version 3 of the License.
00011  *
00012  *      QVision is distributed in the hope that it will be useful,
00013  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *      GNU Lesser General Public License for more details.
00016  *
00017  *      You should have received a copy of the GNU Lesser General Public
00018  *      License along with QVision. If not, see <http://www.gnu.org/licenses/>.
00019  */
00020 
00024 
00025 #include <qvmath/qvdisjointset.h>
00026 #include <qvip/qvimagefeatures/qvcomponenttree.h>
00027 #include <qvcore/qvdefines.h>
00028 
00029 QVComponentTree::QVComponentTree(const QVImage<uChar,1> &image, bool inverseTree, bool useAlternative): numNodes(0), freePoints(0), inverseTree(inverseTree)
00030         {
00031         const uInt cols = image.getCols(), rows = image.getRows();
00032 
00033         this->numNodes = 0;
00034         this->leafNodes = 0;
00035         this->freePoints = 0;
00036         this->totalPoints = 0;
00037         this->maxNodes = cols * rows;
00038         this->nodes.resize(maxNodes/10);        // 10 factor is an heuristic value, estimated from several tries.
00039 
00040         if (inverseTree)
00041                 {
00042                 QVImage<uChar> notImage(cols, rows);
00043 
00044                 QVIMAGE_INIT_READ(uChar,image);
00045                 QVIMAGE_INIT_WRITE(uChar,notImage);
00046                 for (uInt col = 0; col < cols; col++)
00047                         for (uInt row = 0; row < rows; row++)
00048                                 QVIMAGE_PIXEL(notImage, col, row,0) = 255 - QVIMAGE_PIXEL(image, col, row,0);
00049 
00050                 if (useAlternative)
00051                         getComponentTree2(notImage);
00052                 else
00053                         getComponentTree(notImage);
00054                 }
00055         else    {
00056                 if (useAlternative)
00057                         getComponentTree2(image);
00058                 else
00059                         getComponentTree(image);
00060                 }
00061         }
00062 
00063 /*void QVComponentTree::testComponentTree(const QVImage<uChar,1> &image, QVDisjointSet &disjointSet)
00064         {
00065         Q_ASSERT(closedNode(this->rootNodeID));
00066 
00067         // Checking that actually number of nodes, and number of nodes with ID != NULL_NODE equals the
00068         // value holded in this->numNodes.
00069         uInt sumNodes = 0, sumChildNodes = 0, sumLeafNodes = 0;
00070 
00071         // Checking some basic tree structure and values
00072         for (uInt node = 0; node < this->numNodes; node++)
00073                 if (closedNode(node))
00074                         {
00075                         const uInt fThreshold = firstThreshold(node), lThreshold = lastThreshold(node);
00076 
00077                         if (numChilds(node) == 0)
00078                                 sumLeafNodes++;
00079 
00080                         sumNodes++;
00081                         // Checking areas correctness
00082                         Q_ASSERT(area(node)[fThreshold] <= area(node)[lThreshold] != 0);
00083                         Q_ASSERT(area(node)[fThreshold] != 0);
00084                         Q_ASSERT(area(node)[lThreshold] != 0);
00085 
00086                         // Check that seed pixel correspond with first threshold
00087                         Q_ASSERT(image(seedX(node), seedY(node)) == fThreshold);
00088 
00089                         // Check areas go from lesser size to bigger
00090                         uInt lastArea = area(node)[fThreshold];
00091                         for (uInt threshold = fThreshold+1; threshold <= lThreshold; threshold++)
00092                                 if (area(node)[threshold] != 0)
00093                                         {
00094                                         const uInt actualArea = area(node)[threshold];
00095                                         Q_ASSERT(actualArea >= lastArea);
00096                                         lastArea = actualArea;
00097                                         }
00098 
00099                         uInt maxAreasChilds = 0;
00100                         uInt childs = 0;
00101                         for (   uint child = firstChild(node);
00102                                 child != NULL_NODE;
00103                                 child = nextSibling(child), childs++)
00104                                 {
00105                                 Q_ASSERT(childs < numChilds(node));
00106                                 Q_ASSERT(child < this->numNodes);
00107                                 Q_ASSERT(child != rootNode());
00108                                 Q_ASSERT(closedNode(child));
00109                                 maxAreasChilds += area(child)[lastThreshold(child)];
00110                                 }
00111 
00112                         Q_ASSERT(area(node)[firstThreshold(node)] > maxAreasChilds);
00113                         Q_ASSERT(childs == numChilds(node));
00114 
00115                         sumChildNodes += numChilds(node);
00116                 }
00117         qDebug() << "getComponentTree(): /////// estadisticos";
00118         qDebug() << "getComponentTree(): sumNodes = " << sumNodes << sumChildNodes;
00119         Q_ASSERT( sumNodes == (sumChildNodes+1) );
00120         Q_ASSERT( this->leafNodes == sumLeafNodes );
00121 
00122         qDebug() << "getComponentTree(): this->numNodes = " << this->numNodes;
00123         qDebug() << "getComponentTree(): this->freePoints = "<< this->freePoints;
00124         qDebug() << "getComponentTree(): this->totalPoints = "<< this->totalPoints;
00125         qDebug() << "getComponentTree(): this->leafNodes + this->freePoints = "
00126                         << this->leafNodes + this->freePoints;
00127 
00128         Q_ASSERT(disjointSet.numberOfSets() == 1);
00129         Q_ASSERT(disjointSet.getSetCardinality(rootNode()) == (image.getCols() * image.getRows()));
00130         Q_ASSERT(this->totalPoints == (image.getCols() * image.getRows()));
00131         Q_ASSERT(this->totalPoints == this->leafNodes + this->freePoints);
00132         }*/
00133 
00136 
00137 void QVComponentTree::getComponentTree(const QVImage<uChar> &image)
00138         {
00139         qDebug() << "getComponentTree()";
00140         const uInt cols = image.getCols(), rows = image.getRows();
00141 
00142         QVIMAGE_INIT_READ(uChar,image);
00143 
00144         const QVector< QVector< QPoint > > points = CountingSort(image);
00145         QVDisjointSet disjointSet(cols, rows);
00146 
00147         uInt *nodeID = new uInt[maxNodes];
00148         for(uInt i=0; i<maxNodes; i++)
00149                 nodeID[i] = NULL_NODE;
00150 
00151         // This loop creates the structure of the component tree, using the disjoint set, transversiong the pixels of the image
00152         // ordered by their gray-scale value, sorted thanks to 'CountingSort' function.
00153         for (int threshold = 0; threshold < points.size(); threshold++)
00154                 {
00155                 // We join in the disjoint set pixels with gray-scale equal to threshold, with adjacent regions, or pixels, with
00156                 // a gray-scale value equal or lesser than threshold. This is done here only for the disjoint set.
00157                 //
00158                 // Also, here are also joined component tree nodes which have in common one of the processed points.
00159                 for (int n=0; n< points[threshold].size(); n++)
00160                         {
00161                         const uInt      col = points[threshold][n].x(),  
00162                                         row = points[threshold][n].y(), // coordinates of the current pixel
00163                                         actualIndex = disjointSet.index(col, row);  // Index in the disjoint Set of the current pixel
00164                         const uChar     actualPixel = QVIMAGE_PIXEL(image, col, row,0);  // Value of the current pixel
00165                         uInt            actualSet = disjointSet.find(col, row);  // canonical element of the subset
00166 
00167                         // Transverse neighbourhood of a pixel looking for close pixels to join with
00168                         // (those with gray-scale level lower or equal to that of the actual pixel)
00169                         for (uInt i = (uInt) MAX(0,(int)col-1); i< MIN(cols, col+2); i++)  // we look at the 8 rounding neighbours
00170                                 for (uInt j = (uInt) MAX(0,(int)row-1); j< MIN(rows, row+2); j++)
00171                                         if ((col != i) || (row != j))
00172                                         {
00173                                         const uInt vecinoSet = disjointSet.find(i,j);  // neighbour's canonical element
00174                                         const uChar vecinoPixel = QVIMAGE_PIXEL(image, i, j, 0);  // neighbour's gray-level 
00175 
00176                                         if ( (vecinoPixel <= actualPixel) && (vecinoSet != actualSet) )
00177                                                 {
00178                                                 // We should join this pixel to the set of the neighbour
00179                                                 // Each canonical element of a subset has a nodeID element which contains information about the region.
00180                                                 const uInt actualNodeID = nodeID[actualSet], vecinoNodeID = nodeID[vecinoSet];
00181 
00182                                                 actualSet = disjointSet.unify(col, row, i, j); // both subsets are unified.
00183 
00184                                                 Q_ASSERT(disjointSet.find(disjointSet.index(col, row)) == disjointSet.find(disjointSet.index(i, j)));
00185 
00186                                                 // If actual point is not in a node already, we associate it with the point that is
00187                                                 // associated to a node.
00188                                                 if (vecinoNodeID == NULL_NODE)
00189                                                         nodeID[actualSet] = actualNodeID;
00190                                                 else if (actualNodeID == NULL_NODE)
00191                                                         nodeID[actualSet] = vecinoNodeID;
00192                                                 else    // Otherwise, both actual and neighbour are associated to a node already.
00193                                                         // We create a new node, and join both nodes of actual and neighbour pixels to
00194                                                         // that one.
00195                                                         {
00196                                                         // We check that no one of the nodes of actual and neighbour pixels
00197                                                         // is new. In that case it will be parent node.
00198                                                         if (!closedNode(actualNodeID) && closedNode(vecinoNodeID))
00199                                                                 // We just add the node...
00200                                                                 {
00201                                                                 addChild(actualNodeID, vecinoNodeID);
00202                                                                 nodeID[actualSet] = actualNodeID;
00203                                                                 }
00204                                                         else if (closedNode(actualNodeID) && !closedNode(vecinoNodeID))
00205                                                                 // We just add the other node...
00206                                                                 {
00207                                                                 addChild(vecinoNodeID, actualNodeID);
00208                                                                 nodeID[actualSet] = vecinoNodeID;
00209                                                                 }
00210                                                         else if (closedNode(actualNodeID) && closedNode(vecinoNodeID))
00211                                                                 // We have two old nodes, and create a parent to unify them.
00212                                                                 {
00213                                                                 const uInt newNodeID = newNode(col, row, threshold);
00214                                                                 addChild(newNodeID, actualNodeID);
00215                                                                 addChild(newNodeID, vecinoNodeID);
00216 
00217                                                                 //nodeID[actualIndex] = newNodeID;
00218                                                                 nodeID[actualSet] = newNodeID;
00219                                                                 }
00220                                                         else // if ( !NODE(actualNodeID).closed and !NODE(vecinoNodeID).closed )
00221                                                                 // We have two parent nodes, we leave things as they are.
00222                                                                 // No, we should unify both, passing childs of one of them to the
00223                                                                 // other.
00224                                                                 {
00225                                                                 Q_ASSERT(closedNode(actualNodeID) == false);
00226                                                                 Q_ASSERT(closedNode(vecinoNodeID) == false);
00227                                                                 Q_ASSERT(numChilds(actualNodeID) > 0);
00228                                                                 Q_ASSERT(numChilds(vecinoNodeID) > 0);
00229 
00230                                                                 mergeNodes(actualNodeID, vecinoNodeID);
00231                                                                 nodeID[actualSet] = actualNodeID;
00232                                                                 }
00233                                                         }
00234 
00235                                                 // Actualize areas for the resulting parent node.
00236                                                 if (nodeID[actualSet] != NULL_NODE)
00237                                                         {
00239                                                         //Q_ASSERT(area(actualNodeID)[lastThreshold(actualNodeID)] <= disjointSet.getSetCardinality(actualIndex));
00240                                                         lastThreshold(nodeID[actualSet]) = threshold;
00241                                                         area(nodeID[actualSet])[threshold] = disjointSet.getSetCardinality(actualSet);
00242                                                         }
00243 
00244                                                 Q_ASSERT(nodeID[disjointSet.find(disjointSet.index(col, row))] == nodeID[disjointSet.find(disjointSet.index(i, j))]);
00245                                                 }
00246                                         }
00247                         }
00248 
00249                 // In this loop we actualize areas for the gray-level of the threshold of the two old nodes, and create new nodes, 
00250                 // case we find a set of one or several pixels of gray-scale value equal to threshold value, which are not joined
00251                 // to any connected set represented already in a node of the component tree.
00252                 //
00253                 // In this point, we have processed all pixels with gray-scale value equal or lesser to threshold. All of them are
00254                 // grouped to a group of pixels with same gray-scale level, in which case we have the vertex of a node, or well
00255                 // or well joined to a previously created node.
00256                 //
00257                 // Then we creater for the former case new nodes, and in any case we actualize areas for nodes with new points
00258                 // in them.
00259                 for (int n=0; n< points[threshold].size(); n++)
00260                         {
00261                         const uInt      col = points[threshold][n].x(),
00262                                         row = points[threshold][n].y(),
00263                                         actualIndex = disjointSet.index(col, row),
00264                                         actualSet = disjointSet.find(actualIndex);
00265 
00266                         Q_ASSERT_X(threshold < 256, "getComponentTree", "out of bounds 4");
00267                         Q_ASSERT_X(actualIndex < cols * rows, "getComponentTree", "out of bounds 5");
00268 
00269                         // We have a pixel with gray-scale level equal to threshold, and disjoint set identificator equal to
00270                         // himself.
00271                         // This means either it is an isolated pixel, surrounded by pixels of gray-scale level higher than his, or
00272                         // that he is in a connected set of pixels, all of them with exactly gray-scale level value of threshold
00273                         // (and we hill be the only one of that set, with disjoint set identificator equal to himself).
00274                         // Either case we create a new node, with seed point equal to this node.
00275                         if (actualIndex == actualSet)
00276                                 {
00277                                 if (nodeID[actualIndex] == NULL_NODE)
00278                                         // We have a header point for the new component tree node.
00279                                         // We initialize the values for his node.
00280                                         {
00281                                         nodeID[actualSet] = newNode(col, row, threshold);
00282                                         area(nodeID[actualSet])[threshold] = disjointSet.getSetCardinality(actualSet);
00283 
00284                                         this->leafNodes++;
00285                                         }
00286                                 else    // Actual pixel is associated to a node, but this one was created for other pixel.
00287                                         // We count as a free pixel the one that created the node that contains actual pixel.
00288                                         this->freePoints++;
00289                                 }
00290                         else    // Actual pixel is not its group head
00291                                 this->freePoints++;
00292 
00293                         const uInt actualNodeID = nodeID[actualSet];
00294 
00295                         if (actualNodeID != NULL_NODE)
00296                                 {
00297                                 // Actualize histogram for the node of the actual pixel.
00298                                 //lastThreshold(actualNodeID) = threshold;
00299                                 //area(actualNodeID)[threshold] = disjointSet.getSetCardinality(actualIndex);
00300 
00301                                 // Close node for the actual pixel, if open.
00302                                 closedNode(actualNodeID) = true;
00303                                 }
00304 
00305                         // Actualize total number of points processed.
00306                         this->totalPoints++;
00307                         }
00308                 }
00309 
00310         rootNode() = nodeID[disjointSet.find(0)];
00311 
00312         // Component tree finished, performing some tests....
00313         #ifndef QT_NO_DEBUG
00314         //testComponentTree(image, disjointSet);
00315         #endif
00316 
00317         delete nodeID;
00318 
00319         qDebug() << "getComponentTree() <~ return";
00320         }
00321 
00327 
00328 // This macro gets two points by their coordinates (col1, row1) and (col2,row2), and
00329 // tests wether they should be joined, or their sets marked as non-leaf node.
00330 #define TEST_JOIN_PIXELS(col1, row1, col2,row2)                                                         \
00331         {                                                                                               \
00332         const uChar actualPixel = QVIMAGE_PIXEL(image, col1, row1,0);                                   \
00333         const uChar neigbourPixel = QVIMAGE_PIXEL(image, col2, row2,0);                                 \
00334         uInt    actualSet = disjointSet.find(col1,row1), neighbourSet = disjointSet.find(col2,row2);    \
00335                                                                                                         \
00336         if (neigbourPixel == actualPixel)                                                               \
00337                 /* Both pixels have the same gray-scale value: join their sets. */                      \
00338                 {                                                                                       \
00339                 uInt destinationSet = disjointSet.unify(actualSet, neighbourSet);                       \
00340                 isLeafNode[destinationSet] = isLeafNode[actualSet] && isLeafNode[neighbourSet];         \
00341                 }                                                                                       \
00342         else if (neigbourPixel < actualPixel)                                                           \
00343                 /* Mark as non-leaf node the set for the actual pixel. */                               \
00344                 {                                                                                       \
00345                 borderPixel[disjointSet.index(col1,row1)] = true;                                       \
00346                 isLeafNode[actualSet] = false;                                                          \
00347                 }                                                                                       \
00348         else /* if (neigbourPixel > actualPixel) */                                                     \
00349                 /* Mark as non-leaf node the set for the neighbour pixel. */                            \
00350                 {                                                                                       \
00351                 borderPixel[disjointSet.index(col2,row2)] = true;                                       \
00352                 isLeafNode[neighbourSet] = false;                                                       \
00353                 }                                                                                       \
00354         }
00355 
00356 void QVComponentTree::getComponentTree2(const QVImage<uChar> &image)
00357         {
00358         qDebug() << "getComponentTree()";
00359         const uInt cols = image.getCols(), rows = image.getRows();
00360 
00361         this->maxNodes = cols * rows;
00362         //this->nodes.resize(maxNodes/10);      // 10 factor is an heuristic value, estimated from several tries.
00363         this->numNodes = 0;
00364         this->leafNodes = 0;
00365         this->freePoints = 0;
00366         this->totalPoints = 0;
00367 
00368         QVIMAGE_INIT_READ(uChar,image);
00369 
00370         QVDisjointSet disjointSet(cols, rows);
00371 
00373         // Initial join of sets with pixels of same grayscale value
00374         //
00375         bool    *isLeafNode = new bool[maxNodes],
00376                 *borderPixel = new bool[maxNodes];      // IMPROVEMENT: do not compute border pixels.
00377         uInt    *nodeID = new uInt[maxNodes],
00378                 *setID = new uInt[maxNodes];
00379 
00380         for(uInt i=0; i<maxNodes; i++)
00381                 {
00382                 isLeafNode[i] = true;
00383                 borderPixel[i] = false;
00384                 nodeID[i] = NULL_NODE;
00385                 setID[i] = 0;
00386                 }
00387 
00388         // Then we join sets of neighbour pixels with the same gray-scale value
00389         for (int col =0; col < cols-1; col++)
00390                 for (int row =0; row < rows-1; row++)
00391                         {
00392                         const uChar actualPixel = QVIMAGE_PIXEL(image, col, row,0);
00393                         for (int i = col; i< col+2; i++)
00394                                 for (int j = row; j < row + 2; j++)
00395                                         if ((i != col) || (j != row))
00396                                                 TEST_JOIN_PIXELS(col, row, i,j);
00397 
00398                         // This diagonal join can't be done in the previous loop, for top row pixels
00399                         if (row != 0)
00400                                 TEST_JOIN_PIXELS(col, row, col+1, row-1);
00401                         }
00402 
00403         /*std::cout << "Sets:" << std::endl;
00404         for (uInt col =0 ; col < cols; col++)
00405                 for (uInt row =0 ; row < rows; row++)
00406                         {
00407                         uInt actualIndex = disjointSet.index(col, row), actualSet = disjointSet.find(col, row);
00408                         //if ((actualSet == actualIndex))
00409                         //      std::cout << "\tat pixel " << col << ", " << row << ". " << isLeafNode[actualIndex] << std::endl;
00410                         }*/
00411 
00413         // We create the tree structure, and add the leaf nodes
00414         //
00415         // We count the number of leaf nodes, and create the initial data structure.
00416         for (uInt col =0 ; col < cols; col++)
00417                 for (uInt row =0 ; row < rows; row++)
00418                         {
00419                         uInt actualIndex = disjointSet.index(col, row), actualSet = disjointSet.find(col, row);
00420 
00421                         setID[actualIndex] = actualSet;
00422 
00423                         if ((actualSet == actualIndex) && isLeafNode[actualIndex])
00424                                         this->leafNodes++;
00425 
00426                         //if (borderPixel[actualIndex])
00427                         //      std::cout << "(" << col << ", " << row << ")\t";
00428                         }
00429 
00430         // No component tree can have more than 2*leafNodes.This should be because every parent node has always at least
00431         // two siblings, or more.
00432         this->nodes.resize(2*this->leafNodes);
00433         std::cout << "Sets: " << this->leafNodes << std::endl;
00434 
00435         // IMPROVEMENT: move the code of the following loop to the upper loop, and stablish 'nodes' size to a fixed value.
00436         // ... and create the nodes for the leaf nodes
00437         for (uInt col =0 ; col < cols; col++)
00438                 for (uInt row =0 ; row < rows; row++)
00439                         {
00440                         uInt actualIndex = disjointSet.index(col, row);
00441                         if ((setID[actualIndex] == actualIndex) && isLeafNode[actualIndex])
00442                                         nodeID[actualIndex] = newNode(col, row, QVIMAGE_PIXEL(image, col, row,0));
00443                         }
00444 
00445         // This structure will go joining the sets formed in the variable 'disjointSet'.
00446         // It is better for that reason, because is smaller.
00447         QVDisjointSet superSet(this->leafNodes);
00448 
00449         // This loop creates the structure of the component tree, using the disjoint set, transversiong the pixels of the image
00450         // ordered by their gray-scale value, sorted thanks to 'CountingSort' function.
00451         // IMPROVEMENT: construct 'points' set only with border pixels
00452         const QVector< QVector< QPoint > > points = CountingSort(image);
00453         for (int threshold = 0; threshold < points.size(); threshold++)
00454                 {
00455                 // We join in the disjoint set pixels with gray-scale equal to threshold, with adjacent regions, or pixels, with
00456                 // a gray-scale value equal or lesser than threshold. This is done here only for the disjoint set.
00457                 //
00458                 // Also, here are also joined component tree nodes which have in common one of the processed points.
00459                 for (int n=0; n< points[threshold].size(); n++)
00460                         {
00461                         const uInt col = points[threshold][n].x(), row = points[threshold][n].y();
00462 
00463                         // This will eliminate 25% of the pixels in the image.
00464                         if (!borderPixel[disjointSet.index(col, row)])
00465                                 continue;
00466 
00467                         const uInt actualIndex = disjointSet.index(col,row);
00468                         const uChar actualPixel = QVIMAGE_PIXEL(image, col, row,0);
00469                         // Transverse neighbourhood of a pixel looking for close pixels to join with
00470                         // (those with gray-scale level lower or equal to that of the actual pixel)
00471                         for (uInt i = (uInt) MAX(0,(int)col-1); i< MIN(cols, col+2); i++)
00472                                 for (uInt j = (uInt) MAX(0,(int)row-1); j< MIN(rows, row+2); j++)
00473                                         if ((col != i) || (row != j))
00474                                         {
00475                                         const uInt vecinoIndex = disjointSet.index(i,j);
00476                                         const uChar vecinoPixel = QVIMAGE_PIXEL(image, i, j,0);
00477 
00478                                         if (actualPixel > vecinoPixel)
00479                                                 {
00480                                                 const uInt vecinoSet = setID[vecinoIndex], actualSet = setID[actualIndex];
00481 
00482                                                 // If we got here, is because pixels are different, so their main set.
00483                                                 Q_ASSERT(vecinoSet != actualSet);
00484 
00485                                                 const uInt vecinoNode = nodeID[vecinoSet], actualNode = nodeID[actualSet];
00486 
00487                                                 // Any pixel with a greater value should be joined to a set                                             
00488                                                 Q_ASSERT(vecinoNode != NULL_NODE);
00489 
00490                                                 //const uInt vecinoSuperSet = superSet.find(nodeID[vecinoSet]);
00491                                                 //const uInt actualSuperSet = superSet.find(nodeID[actualSet]);
00492 
00493                                                 //std::cout << "***" << vecinoNode << " " << NULL_NODE << std::endl;
00494                                                 if (actualNode == NULL_NODE)
00495                                                         nodeID[actualSet] = vecinoNode;
00496                                                 /*else if (!closedNode(actualNode) && !closedNode(vecinoNode))
00497                                                         {
00498                                                         const uInt newNodeID = newNode(col, row, threshold);
00499 
00500                                                         nodeID[disjointSet.index(col, row)] = newNodeID;
00501                                                         addChild(newNodeID, actualNode);
00502                                                         addChild(newNodeID, vecinoNode);
00503                                                         nodeID[actualSet] = newNodeID;
00504                                                         }       */
00505                                                 }
00506                                         }
00507                         }
00508 
00509                 // We close nodes, so in a future new branches will not be added to them.
00510                 for (int n=0; n< points[threshold].size(); n++)
00511                         {
00512                         const uInt col = points[threshold][n].x(), row = points[threshold][n].y();
00513 
00514                         if (!borderPixel[disjointSet.index(col, row)])
00515                                 continue;
00516 
00517                         const uInt actualIndex = disjointSet.index(col,row);
00518                         const uInt actualSet = setID[actualIndex];
00519                         const uInt actualNode = nodeID[actualSet];
00520 
00521                         closedNode(actualNode) = true;
00522                         }
00523                 }
00524 
00525         rootNode() = nodeID[disjointSet.find(0)];
00526 
00527         // COMPONENT TREE FINISHED. STARTING TESTS...
00528         #ifndef QT_NO_DEBUG
00529         //testComponentTree();
00530         #endif
00531 
00532         delete borderPixel;
00533         delete isLeafNode;
00534         delete nodeID;
00535         delete setID;
00536 
00537         qDebug() << "getComponentTree() <~ return";
00538         }
00539 
00540 

Generated on Thu Jul 17 17:23:28 2008 for QVision by  doxygen 1.5.3