00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <qvdta/qvcontour.h>
00026
00027 namespace qvdta
00028 {
00029
00030
00031
00032
00033
00034
00036 const char coorX8Connect[8] = { 0, 1, 1, 1, 0, -1, -1, -1 };
00037 const char coorY8Connect[8] = { -1, -1, 0, 1, 1, 1, 0, -1 };
00038 const char coorX4Connect[4] = { 0, 1, 0, -1, };
00039 const char coorY4Connect[4] = { -1, 0, 1, 0, };
00040 const char coorX4Diag[8] = { 1, 1, -1, -1 };
00041 const char coorY4Diag[8] = { -1, 1, 1, -1 };
00043
00044
00046 QVPolyline getConnectedSetBorderContourThresholdFromBorderPoint(const QVImage<uChar> &image, const int startPointX, const int startPointY, const uChar threshold)
00047 {
00048 QVPolyline lista;
00049
00050 lista.closed = true;
00051 lista.append(QPoint(startPointX, startPointY));
00052
00053 QVIMAGE_INIT_READ(uChar,image);
00054 QRect roi = image.getROI();
00055
00056 Q_ASSERT_X(roi.contains(startPointX, startPointY), "getContourThresholdFromBorderPoint", "start point out of image ROI");
00057 Q_ASSERT_X(QVIMAGE_PIXEL(image, startPointX, startPointY, 0) >= threshold, "getContourThresholdFromBorderPoint", "start point is not contained in a connected set");
00058
00059
00060
00061 uChar searchDir = 128, numOuterPixels = 0;
00062 for (int i = 0; i<8; i++)
00063 {
00064 int x = startPointX +coorX8Connect[i], y = startPointY +coorY8Connect[i];
00065 if (!roi.contains(x, y))
00066 {
00067 numOuterPixels++;
00068 searchDir = i;
00069 }
00070 else if (QVIMAGE_PIXEL(image, x, y,0) < threshold)
00071 {
00072 numOuterPixels++;
00073 searchDir = i;
00074 }
00075 }
00076
00077
00078 Q_ASSERT_X(searchDir < 8, "getContourThresholdFromBorderPoint", "start point is inside the set, not in the border");
00079
00080
00081 if (numOuterPixels == 8)
00082 return lista;
00083
00084
00085 int sumSearchDir = 0, actualPointX = startPointX, actualPointY = startPointY;
00086 while (true)
00087 {
00088
00089 uChar d;
00090 int nextPointX, nextPointY;
00091 for (d = 0; d < 8; d++)
00092 {
00093 searchDir = (searchDir+1)%8;
00094 nextPointX = actualPointX + coorX8Connect[searchDir];
00095 nextPointY = actualPointY + coorY8Connect[searchDir];
00096 if (roi.contains(nextPointX, nextPointY))
00097 if ( (QVIMAGE_PIXEL(image, nextPointX, nextPointY,0) >= threshold) )
00098 break;
00099 }
00100
00101 sumSearchDir += d - 3;
00102
00103 actualPointX = nextPointX;
00104 actualPointY = nextPointY;
00105
00106 if ( QVIMAGE_PIXEL(image, actualPointX, actualPointY,0) < threshold )
00107 break;
00108
00109 if ( startPointX == actualPointX && startPointY == actualPointY)
00110 break;
00111
00112 lista.append(QPoint(actualPointX, actualPointY));
00113 searchDir = searchDir + 4;
00114 }
00115
00116 lista.direction = (sumSearchDir >= 0);
00117 return lista;
00118 }
00120
00121 QVPolyline getConnectedSetBorderContourThreshold(const QVImage<uChar> &image, const QPoint startPoint, const uChar threshold)
00122 {
00123 QVIMAGE_INIT_READ(uChar,image);
00124 const QRect roi = image.getROI();
00125
00126 int col = startPoint.x(), row = startPoint.y();
00127
00128 if (QVIMAGE_PIXEL(image, col, row,0) < threshold)
00129 return QVPolyline();
00130
00131 while (roi.contains(col+1, row))
00132 {
00133 if ( QVIMAGE_PIXEL(image, col+1, row,0) < threshold )
00134 break;
00135 col++;
00136 }
00137
00138 return getConnectedSetBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00139 }
00140
00141 QList<QVPolyline> getConnectedSetBorderContoursThreshold(const QVImage <uChar> &image, const uChar threshold)
00142 {
00143 qDebug() << "getPolylinesThreshold()";
00144 QVImage<uChar> mask(image.getCols()+1, image.getRows()+1);
00145 qvipp::Set(mask,0);
00146
00147 QVIMAGE_INIT_READ(uChar,image);
00148 QVIMAGE_INIT_WRITE(uChar,mask);
00149
00150 QRect roi = image.getROI();
00151
00152 QList<QVPolyline> polylineList;
00153
00154
00155 for (int row = roi.y(); row < roi.y() + roi.height(); row++)
00156 for (int col = roi.x(); col < roi.y() + roi.width(); col++)
00157 {
00158
00159 if (QVIMAGE_PIXEL(image, col, row,0) >= threshold)
00160 {
00161
00162 if ( !QVIMAGE_PIXEL(mask, col, row,0) )
00163 {
00164 QVPolyline lista = getConnectedSetBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00165 draw(mask, lista, true, true);
00166 polylineList.append(lista);
00167 }
00168
00169
00170 while (roi.contains(col+1, row))
00171 {
00172 if ( QVIMAGE_PIXEL(image, col+1, row,0) < threshold )
00173 break;
00174 col++;
00175 }
00176
00177
00178 if ( !QVIMAGE_PIXEL(mask, col, row,0) )
00179 {
00180 QVPolyline lista = getConnectedSetBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00181 draw(mask, lista, true, true);
00182 polylineList.append(lista);
00183 }
00184 }
00185
00186 }
00187 qDebug() << "getPolylinesThreshold():"<< polylineList.size() << "contours obtained";
00188 qDebug() << "getPolylinesThreshold() <~ return";
00189 return polylineList;
00190 }
00191
00193
00194 QVPolyline getLineContourThreshold4Connectivity(QVImage<uChar> &image, const QPoint point, QVPolyline &polyline, const uChar threshold, bool reverse)
00195 {
00196 const uInt cols = image.getCols(), rows = image.getRows();
00197 QVIMAGE_INIT_WRITE(uChar, image);
00198
00199 uInt lastDir = 666, coorX = point.x(), coorY = point.y();
00200
00201 qDebug() << "\tContour: new contour";
00202
00203 while(true)
00204 {
00205 qDebug() << "\tContour:\tAppending point (" << coorX << ", " << coorY << ")";
00206 if (reverse)
00207 polyline.prepend(QPoint(coorX, coorY));
00208 else
00209 polyline.append(QPoint(coorX, coorY));
00210
00211 QVIMAGE_PIXEL(image, coorX, coorY, 0) = 0;
00212
00213 uInt dir;
00214 int newCoorX, newCoorY;
00215 for (dir = 0; dir < 4; dir++)
00216 {
00217 newCoorX = coorX + coorX4Connect[dir];
00218 newCoorY = coorY + coorY4Connect[dir];
00219
00220
00221 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00222 continue;
00223
00224
00225 if ( (QVIMAGE_PIXEL(image, newCoorX, newCoorY, 0) >= threshold) && (lastDir != dir) )
00226 break;
00227 }
00228
00229 if (dir == 4) break;
00230
00231 coorX = newCoorX;
00232 coorY = newCoorY;
00233 lastDir = (dir+2)%4;
00234 }
00235
00236 return polyline;
00237 }
00238
00239 QList<QVPolyline> getLineContoursThreshold4Connectivity(const QVImage<uChar> &image, const uChar threshold)
00240 {
00241 const uInt cols = image.getCols(), rows = image.getRows();
00242 QVImage<uChar> clone = image;
00243
00244 QList<QVPolyline> polylineList;
00245
00246
00247 for(uInt col = 0; col < cols; col++)
00248 for(uInt row = 0; row < rows; row++)
00249 {
00250 QVIMAGE_INIT_READ(uChar, clone);
00251
00252 if ( (QVIMAGE_PIXEL(clone, col, row, 0) < threshold) )
00253 continue;
00254
00255
00256 QVPolyline polyline;
00257
00258
00259 getLineContourThreshold4Connectivity(clone, QPoint(col, row), polyline, threshold, false);
00260
00261
00262 uInt dir;
00263 int newCoorX, newCoorY;
00264 for (dir = 0; dir < 4; dir++)
00265 {
00266 newCoorX = col + coorX4Connect[dir];
00267 newCoorY = row + coorY4Connect[dir];
00268
00269
00270 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00271 continue;
00272
00273
00274 if ( (clone(newCoorX, newCoorY) >= threshold) )
00275 break;
00276 }
00277
00278
00279 if (dir != 4)
00280 getLineContourThreshold4Connectivity(clone, QPoint(newCoorX, newCoorY), polyline, threshold, true);
00281
00282
00283 polylineList.append(polyline);
00284 }
00285
00286 return polylineList;
00287 }
00288
00290
00291 QVPolyline getLineContourThreshold8Connectivity(QVImage<uChar> &image, const QPoint point, QVPolyline &polyline, const uChar threshold, bool reverse)
00292 {
00293 const uInt cols = image.getCols(), rows = image.getRows();
00294 QVIMAGE_INIT_WRITE(uChar, image);
00295
00296 uInt lastDir = 666, coorX = point.x(), coorY = point.y();
00297
00298 qDebug() << "\tContour: new contour";
00299
00300 bool continueCond = true;
00301 while(continueCond)
00302 {
00303 qDebug() << "\tContour:\tAppending point (" << coorX << ", " << coorY << ")";
00304 if (reverse)
00305 polyline.prepend(QPoint(coorX, coorY));
00306 else
00307 polyline.append(QPoint(coorX, coorY));
00308
00309 QVIMAGE_PIXEL(image, coorX, coorY, 0) = 0;
00310
00311
00312 uInt dir;
00313 int newCoorX, newCoorY;
00314 for (dir = 0; dir < 4; dir++)
00315 {
00316 newCoorX = coorX + coorX4Connect[dir];
00317 newCoorY = coorY + coorY4Connect[dir];
00318
00319
00320 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00321 continue;
00322
00323
00324 if ( (QVIMAGE_PIXEL(image, newCoorX, newCoorY, 0) >= threshold) && (lastDir != dir) )
00325 break;
00326 }
00327
00328 if (dir == 4)
00329 {
00330
00331 uInt dir;
00332 int newCoorX, newCoorY;
00333 for (dir = 0; dir < 4; dir++)
00334 {
00335 newCoorX = coorX + coorX4Diag[dir];
00336 newCoorY = coorY + coorY4Diag[dir];
00337
00338
00339 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00340 continue;
00341
00342
00343 if ( (QVIMAGE_PIXEL(image, newCoorX, newCoorY, 0) >= threshold) && (lastDir != dir) )
00344 break;
00345 }
00346 if (dir == 4) break;
00347
00348 coorX = newCoorX;
00349 coorY = newCoorY;
00350 lastDir = (dir+2)%4;
00351 }
00352 else {
00353 coorX = newCoorX;
00354 coorY = newCoorY;
00355 lastDir = (dir+2)%4;
00356 }
00357 }
00358
00359 return polyline;
00360 }
00361
00362 QList<QVPolyline> getLineContoursThreshold8Connectivity(const QVImage<uChar> &image, const uChar threshold)
00363 {
00364 const uInt cols = image.getCols(), rows = image.getRows();
00365 QVImage<uChar> clone = image;
00366
00367 QList<QVPolyline> polylineList;
00368
00369
00370 for(uInt col = 0; col < cols; col++)
00371 for(uInt row = 0; row < rows; row++)
00372 {
00373 QVIMAGE_INIT_READ(uChar, clone);
00374
00375 if ( (QVIMAGE_PIXEL(clone, col, row, 0) < threshold) )
00376 continue;
00377
00378
00379 QVPolyline polyline;
00380
00381
00382 getLineContourThreshold8Connectivity(clone, QPoint(col, row), polyline, threshold, false);
00383
00384
00385 uInt dir;
00386 int newCoorX, newCoorY;
00387 for (dir = 0; dir < 4; dir++)
00388 {
00389 newCoorX = col + coorX4Connect[dir];
00390 newCoorY = row + coorY4Connect[dir];
00391
00392
00393 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00394 continue;
00395
00396
00397 if ( (clone(newCoorX, newCoorY) >= threshold) )
00398 break;
00399 }
00400
00401
00402 if (dir != 4)
00403 getLineContourThreshold8Connectivity(clone, QPoint(newCoorX, newCoorY), polyline, threshold, true);
00404 else {
00405
00406 uInt dir;
00407 int newCoorX, newCoorY;
00408 for (dir = 0; dir < 4; dir++)
00409 {
00410 newCoorX = col + coorX4Diag[dir];
00411 newCoorY = row + coorY4Diag[dir];
00412
00413
00414 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00415 continue;
00416
00417
00418 if ( (clone(newCoorX, newCoorY) >= threshold) )
00419 break;
00420 }
00421
00422
00423 if (dir != 4)
00424 getLineContourThreshold8Connectivity(clone, QPoint(newCoorX, newCoorY), polyline, threshold, true);
00425 }
00426
00427
00428 polylineList.append(polyline);
00429 }
00430
00431 return polylineList;
00432 }
00433
00434 }