src/qvdta/qvcontour.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 <qvdta/qvcontour.h>
00026 
00027 namespace qvdta
00028 {
00029 // Direction-nĂºmero            Y
00030 //      NE-7    N-0     NW-1    |
00031 //      E-6     *       W-2     v
00032 //      SE-5    S-4     SW-3
00033 // X -->
00034 //                              N       NO      O       SO      S       SE      E       NE
00035 const char      coorX[8] = {    0,      1,      1,      1,      0,      -1,     -1,     -1 };
00036 const char      coorY[8] = {    -1,     -1,     0,      1,      1,      1,      0,      -1 };
00037 
00038 // Auxiliar function for border extraction. It gets a border point, and the direction where there is one of the outside of the connected-set pixels.
00039 QVPolyline getBorderContourThresholdFromBorderPoint(const QVImage<uChar> &image, const int startPointX, const int startPointY, const uChar threshold)
00040         {
00041         QVPolyline lista;
00042 
00043         lista.closed = true;
00044         lista.append(QPoint(startPointX, startPointY));
00045 
00046         QVIMAGE_INIT_READ(uChar,image);
00047         QRect roi = image.getROI();
00048 
00049         Q_ASSERT_X(roi.contains(startPointX, startPointY), "getContourThresholdFromBorderPoint", "start point out of image ROI");
00050         Q_ASSERT_X(QVIMAGE_PIXEL(image, startPointX, startPointY, 0) >= threshold, "getContourThresholdFromBorderPoint", "start point is not contained in a connected set");
00051 
00052         // We check this is not an interior pixel, neither a solitary one.
00053         // Also we look for a neighbour pixel not belonging to any connected set.
00054         uChar searchDir = 128, numOuterPixels = 0;
00055         for (int i = 0; i<8; i++)
00056                 {
00057                 int x =  startPointX +coorX[i], y =  startPointY +coorY[i];
00058                 if (!roi.contains(x, y))
00059                         {
00060                         numOuterPixels++;
00061                         searchDir = i;
00062                         }
00063                 else if (QVIMAGE_PIXEL(image, x, y,0) < threshold)
00064                         {
00065                         numOuterPixels++;
00066                         searchDir = i;
00067                         }
00068                 }
00069 
00070         // Case we receive an interior pixel, raise assert.
00071         Q_ASSERT_X(searchDir < 8, "getContourThresholdFromBorderPoint", "start point is inside the set, not in the border");
00072 
00073         // Case we have a solitary pixel, we return that pixel.
00074         if (numOuterPixels == 8)
00075                 return lista;
00076 
00077         // We insert each point of the border contour, inserting it to the point list.
00078         int sumSearchDir = 0, actualPointX = startPointX, actualPointY = startPointY;
00079         while (true)
00080                 {
00081                 // We search for the next point belonging to the contour.
00082                 uChar d;
00083                 int     nextPointX, nextPointY;
00084                 for (d = 0; d < 8; d++)
00085                         {
00086                         searchDir = (searchDir+1)%8;
00087                         nextPointX = actualPointX + coorX[searchDir];
00088                         nextPointY = actualPointY + coorY[searchDir];
00089                         if (roi.contains(nextPointX, nextPointY))
00090                                 if ( (QVIMAGE_PIXEL(image, nextPointX, nextPointY,0) >= threshold) )
00091                                         break;
00092                         }
00093 
00094                 sumSearchDir += d - 3;
00095 
00096                 actualPointX = nextPointX;
00097                 actualPointY = nextPointY;
00098 
00099                 if ( QVIMAGE_PIXEL(image, actualPointX, actualPointY,0) < threshold )
00100                         break;
00101 
00102                 if ( startPointX == actualPointX && startPointY == actualPointY)
00103                         break;
00104 
00105                 lista.append(QPoint(actualPointX, actualPointY));
00106                 searchDir = searchDir + 4;
00107                 }
00108 
00109         lista.direction = (sumSearchDir >= 0);
00110         return lista;
00111         }
00112 
00113 QVPolyline getBorderContourThreshold(const QVImage<uChar> &image, const QPoint startPoint, const uChar threshold)
00114         {
00115         QVIMAGE_INIT_READ(uChar,image);
00116         const QRect roi = image.getROI();
00117 
00118         int col = startPoint.x(), row = startPoint.y();
00119 
00120         if (QVIMAGE_PIXEL(image, col, row,0) < threshold)
00121                 return QVPolyline();
00122 
00123         while (roi.contains(col+1, row))
00124                 {
00125                 if ( QVIMAGE_PIXEL(image, col+1, row,0) < threshold )
00126                         break;
00127                 col++;
00128                 }
00129 
00130         return getBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00131         }
00132 
00133 QList<QVPolyline> getBorderContoursThreshold(const QVImage <uChar> &image, const uChar threshold)
00134         {
00135         qDebug() << "getPolylinesThreshold()";
00136         QVImage<uChar> mask(image.getCols()+1, image.getRows()+1);
00137         qvipp::Set(mask,0);
00138 
00139         QVIMAGE_INIT_READ(uChar,image);
00140         QVIMAGE_INIT_WRITE(uChar,mask);
00141 
00142         QRect roi = image.getROI();
00143 
00144         QList<QVPolyline> polylineList;
00145 
00146         // We look for pixels contained in a connected set (gray-level value >= threshold) in the image
00147         for (int row = roi.y(); row < roi.y() + roi.height(); row++)
00148                 for (int col = roi.x(); col < roi.y() + roi.width(); col++)
00149                         {
00150                         // If we find any pixel like that, we can be sure (because the search we did) it belongs to it's border.
00151                         if (QVIMAGE_PIXEL(image, col, row,0) >= threshold)
00152                                 {
00153                                 // if pixel is not marked, we get it's contour
00154                                 if ( !QVIMAGE_PIXEL(mask, col, row,0) )
00155                                         {
00156                                         QVPolyline lista = getBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00157                                         draw(mask, lista, true, true);
00158                                         polylineList.append(lista);
00159                                         }
00160 
00161                                 // We ensure next pixel we process will not belong to a connected set.
00162                                 while (roi.contains(col+1, row))
00163                                         {
00164                                         if ( QVIMAGE_PIXEL(image, col+1, row,0) < threshold )
00165                                                 break;
00166                                         col++;
00167                                         }
00168 
00169                                 // This is for the case in which we find an internal contour, that has not been processed and marked.
00170                                 if ( !QVIMAGE_PIXEL(mask, col, row,0) )
00171                                         {
00172                                         QVPolyline lista = getBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00173                                         draw(mask, lista, true, true);
00174                                         polylineList.append(lista);
00175                                         }
00176                                 }
00177 
00178                         }
00179         qDebug() << "getPolylinesThreshold():"<< polylineList.size() << "contours obtained";
00180         qDebug() << "getPolylinesThreshold() <~ return";
00181         return polylineList;
00182         }
00183 }

Generated on Thu Dec 13 13:06:26 2007 for QVision by  doxygen 1.5.3