00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <qvcore/qvdefines.h>
00026 #include <qvip/qvpolyline.h>
00027 #include <qvip/qvpolylinef.h>
00028 #include <qvmath/qvmatrixalgebra.h>
00029
00030 #include <iostream>
00031 #include <float.h>
00032
00034
00035
00036
00037 #ifndef DOXYGEN_IGNORE_THIS
00038 class ClassAuxIPE
00039 {
00040 public:
00041 double cost;
00042 int index;
00043 ClassAuxIPE *prev,*next;
00044 };
00045
00046 bool costLessThan(ClassAuxIPE* &s1,ClassAuxIPE* &s2)
00047 {
00048 return s1->cost < s2->cost;
00049 }
00050
00051 bool indexLessThan(ClassAuxIPE* &s1,ClassAuxIPE* &s2)
00052 {
00053 return s1->index < s2->index;
00054 }
00055
00056 inline double costElimination(const QVPolyline &polyline,int ia, int ib, int ic)
00057 {
00058 double xA,yA,xB,yB,xC,yC;
00059 xA = polyline[ia].x(); yA=polyline[ia].y();
00060 xB = polyline[ib].x(); yB=polyline[ib].y();
00061 xC = polyline[ic].x(); yC=polyline[ic].y();
00062 if((xA != xC) or (yA != yC))
00063 return ABS(xA*(yC-yB) + xB*(yA-yC) + xC*(yB-yA)) / sqrt((xA-xC)*(xA-xC)+(yA-yC)*(yA-yC));
00064 else
00065 return sqrt((xB-xC)*(xB-xC)+(yB-yC)*(yB-yC));
00066 }
00067
00068 class auxLine {
00069 public:
00070 auxLine(double l1,double l2,double l3,bool ok) : l1(l1),l2(l2),l3(l3),ok(ok) {};
00071 double l1,l2,l3;
00072 bool ok;
00073 };
00074 #endif
00075
00076 double IterativePointElimination(const QVPolyline &polyline, QVPolyline &result,
00077 const double param, bool maxNumberOfPointsMethod,bool intersectLines,
00078 double *max_removed_cost)
00079 {
00080 const uInt tot_siz = polyline.size();
00081 QList<ClassAuxIPE*> list;
00082
00083
00084 result.clear();
00085
00086
00087 if(max_removed_cost != NULL) *max_removed_cost = 0.0;
00088
00089
00090
00091 if(polyline.size()<3)
00092 {
00093 result = polyline;
00094 return FLT_MAX;
00095 }
00096
00097
00098 for(uInt i=0;i<tot_siz;i++)
00099 list.push_back(new ClassAuxIPE);
00100
00101 for(uInt i=0;i<tot_siz;i++)
00102 {
00103 int ia = (i==0)?tot_siz-1:i-1, ib = i, ic = (i==tot_siz-1)?0:i+1;
00104 list[i]->cost = costElimination(polyline,ia,ib,ic);
00105 list[i]->index = ib;
00106 list[i]->prev = list[ia];
00107 list[i]->next = list[ic];
00108 }
00109 if(not polyline.closed)
00110 {
00111 list[0]->cost = FLT_MAX;
00112 list[tot_siz-1]->cost = FLT_MAX;
00113 }
00114 qSort(list.begin(),list.end(),costLessThan);
00115
00116
00117 while(TRUE)
00118 {
00119
00120 if( (list.size() == 3) or
00121 ((not maxNumberOfPointsMethod) and (list[0]->cost > param)) or
00122 ((maxNumberOfPointsMethod) and
00123 (list.size() <= static_cast<int>(param))) )
00124 break;
00125
00126
00127 ClassAuxIPE *elem = list.takeAt(0),
00128 *elemPrev = list.takeAt(list.indexOf(elem->prev)),
00129 *elemNext = list.takeAt(list.indexOf(elem->next));
00130 elemPrev->next = elem->next;
00131 elemNext->prev = elem->prev;
00132 if(elemPrev->cost != FLT_MAX)
00133 elemPrev->cost = costElimination(polyline,elemPrev->prev->index,
00134 elemPrev->index,
00135 elemPrev->next->index);
00136 if(elemNext->cost != FLT_MAX)
00137 elemNext->cost = costElimination(polyline,elemNext->prev->index,
00138 elemNext->index,
00139 elemNext->next->index);
00140
00141
00142 int here;
00143 for(int i=0;i<2;i++)
00144 {
00145 ClassAuxIPE* newelem = ((i==0)?elemNext:elemPrev);
00146 int first=0,last=list.size()-1;
00147 while (first <= last) {
00148 int mid = (first + last) / 2;
00149 if (newelem->cost > list[mid]->cost)
00150 first = mid + 1;
00151 else if (newelem->cost < list[mid]->cost)
00152 last = mid - 1;
00153 else
00154 {
00155 here = mid;
00156 break;
00157 }
00158 }
00159 if(first>last)
00160 here=first;
00161 list.insert(here,newelem);
00162
00163 }
00164
00165 if(max_removed_cost != NULL)
00166 if(elem->cost > *max_removed_cost)
00167 *max_removed_cost = elem->cost;
00168 delete elem;
00169 }
00170
00171
00172 double return_value = list.first()->cost;
00173
00174
00175 qSort(list.begin(),list.end(),indexLessThan);
00176
00177
00178 QList<ClassAuxIPE*>::iterator it = list.begin();
00179 if(intersectLines)
00180 {
00181
00182 double ratio_eig=1.0;
00183 QList<auxLine> lines;
00184 for(int i=0;i<list.size();i++)
00185 {
00186
00187 if((not polyline.closed) and (i==list.size()-1))
00188 break;
00189 int i1 = list[i]->index;
00190 int i2 = list[(i+1)%list.size()]->index;
00191 if(i2<i1) i2 += tot_siz;
00192 int dist = i2-i1+1;
00193 #define MIN_PIXELS_IPE_LINE 15
00194 if(dist >= MIN_PIXELS_IPE_LINE)
00195 {
00196 i1 = (i1+dist/5)%tot_siz;
00197 i2 = (i2-dist/5)%tot_siz;
00198 dist = dist-2*(dist/5);
00199 }
00200 else
00201 {
00202 dist = i2-i1+1;
00203 i1 = i1%tot_siz;
00204 i2 = i2%tot_siz;
00205 }
00206
00207 double x=0,y=0,xx=0,xy=0,yy=0;
00208 uInt j=i1;
00209 do
00210 {
00211 x += polyline[j].x();
00212 y += polyline[j].y();
00213 xx += polyline[j].x()*polyline[j].x();
00214 xy += polyline[j].x()*polyline[j].y();
00215 yy += polyline[j].y()*polyline[j].y();
00216 j = (j+1)%tot_siz;
00217 } while(j!=(i2+1)%tot_siz);
00218 double l1,l2,l3;
00219 x /= dist; y /= dist; xx /= dist; xy /= dist; yy /= dist;
00220
00221 ratio_eig = homogLineFromMoments(x,y,xx,xy,yy,l1,l2,l3);
00222 lines.push_back(auxLine(l1,l2,l3,ratio_eig < 0.1));
00223 }
00224
00225 for(int i=0;i<list.size();i++)
00226 {
00227 QPoint oldPoint = polyline[list[i]->index];
00228 if( (not polyline.closed) and ((i==0) or (i==list.size()-1)))
00229 {
00230
00231 result.append(oldPoint);
00232 continue;
00233 }
00234 int ant = (i-1+list.size())%list.size();
00235 int post = (i+1)%list.size();
00236 double newx = (lines[i].l2)*(lines[ant].l3) - (lines[i].l3)*(lines[ant].l2);
00237 double newy = -(lines[i].l1)*(lines[ant].l3) + (lines[i].l3)*(lines[ant].l1);
00238 double newz = (lines[i].l1)*(lines[ant].l2) - (lines[i].l2)*(lines[ant].l1);
00239 if ( (not lines[i].ok) or (not lines[ant].ok) or
00240 (fabs(newz) < EPSILON) )
00241 result.append(oldPoint);
00242 else
00243 {
00244 int nx = qRound(newx/newz);
00245 int ny = qRound(newy/newz);
00246
00247
00248
00249
00250 double dist =
00251 sqrt((nx-oldPoint.x())*(nx-oldPoint.x()) +
00252 (ny-oldPoint.y())*(ny-oldPoint.y()));
00253 QPoint prevPoint = polyline[list[ant]->index],
00254 nextPoint = polyline[list[post]->index];
00255 double minDist =
00256 qMin(
00257 sqrt((prevPoint.x()-oldPoint.x())*(prevPoint.x()-oldPoint.x()) +
00258 (prevPoint.y()-oldPoint.y())*(prevPoint.y()-oldPoint.y())),
00259 sqrt((nextPoint.x()-oldPoint.x())*(nextPoint.x()-oldPoint.x()) +
00260 (nextPoint.y()-oldPoint.y())*(nextPoint.y()-oldPoint.y()))
00261 );
00262 if(dist < 0.2*minDist)
00263 result.append(QPoint(nx,ny));
00264 else
00265 result.append(oldPoint);
00266 }
00267 }
00268 }
00269 else
00270 {
00271
00272 it = list.begin();
00273 while(it != list.end())
00274 {
00275 result.append(polyline.at((*it)->index));
00276 it++;
00277 }
00278 }
00279
00280
00281 while (!list.isEmpty())
00282 delete list.takeFirst();
00283
00284
00285 result.closed = polyline.closed;
00286 result.direction = polyline.direction;
00287
00288
00289 return return_value;
00290 }
00291
00292
00293
00294 QVPolyline::QVPolyline(): QList<QPoint>(),
00295 closed(false), direction(false)
00296 {
00297 qDebug() << "QVPolyline()";
00298 qDebug() << "QVPolyline() <~ return";
00299 };
00300
00301 QVPolyline::QVPolyline(const QVPolyline &polyline): QList<QPoint>(polyline),
00302 closed(polyline.closed), direction(polyline.direction)
00303 {
00304 qDebug() << "QVPolyline(const QVPolyline &)";
00305 qDebug() << "QVPolyline(const QVPolyline &) <~ return";
00306 };
00307
00308 QVPolyline::QVPolyline(const QVPolylineF &polyline): QList<QPoint>(),
00309 closed(polyline.closed), direction(polyline.direction)
00310 {
00311 foreach(QPointF pointf, polyline)
00312 {
00313 append( QPoint(pointf.toPoint()) );
00314 }
00315 qDebug() << "QVPolylineF(const QVPolylineF &)";
00316 qDebug() << "QVPolylineF(const QVPolylineF &) <~ return";
00317 };
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00342
00343 QVPolyline QVPolyline::ellipse(uInt n, float x, float y, float maxRadio, float minRadio, float ang)
00344 {
00345 QVPolyline ellipse;
00346 float w = 2*PI/(n-1);
00347 float maxArg = (maxRadio+minRadio)/2;
00348 float minArg = (maxRadio-minRadio)/2;
00349
00350 for (uInt t = 0; t < n; t++)
00351 ellipse.append(QPoint ( (uInt) (x + maxArg*cos(ang+w*t) + minArg*cos(ang-w*t)),
00352 (uInt) (y + maxArg*sin(ang+w*t) + minArg*sin(ang-w*t))
00353 ));
00354 return ellipse;
00355 }
00356
00357 QVPolyline QVPolyline::rectangle(int x1, int y1, int x2, int y2)
00358 {
00359 QVPolyline rectangle;
00360 rectangle.append(QPoint( x1, y1 ));
00361 rectangle.append(QPoint( x1, y2 ));
00362 rectangle.append(QPoint( x2, y2 ));
00363 rectangle.append(QPoint( x2, y1 ));
00364 rectangle.append(QPoint( x1, y1 ));
00365 return rectangle;
00366 }
00367
00368 QVPolyline QVPolyline::line(int x1, int y1, int x2, int y2)
00369 {
00370 QVPolyline line;
00371
00372 line.append(QPoint( x1, y1 ));
00373
00374 if (x1 == x2 && y1 == y2)
00375 return line;
00376
00377 int i,dx,dy,sdx,sdy,dxabs,dyabs,x,y,px,py;
00378
00379 dx=x2-x1;
00380 dy=y2-y1;
00381 dxabs=abs(dx);
00382 dyabs=abs(dy);
00383 sdx=SIGN(dx);
00384 sdy=SIGN(dy);
00385 x=dyabs>>1;
00386 y=dxabs>>1;
00387 px=x1;
00388 py=y1;
00389
00390 if (dxabs>=dyabs)
00391 for(i=0;i<dxabs;i++)
00392 {
00393 y+=dyabs;
00394 if (y>=dxabs)
00395 {
00396 y-=dxabs;
00397 py+=sdy;
00398 }
00399 px+=sdx;
00400 line.append(QPoint( px, py ));
00401 }
00402 else
00403 for(i=0;i<dyabs;i++)
00404 {
00405 x+=dxabs;
00406 if (x>=dyabs)
00407 {
00408 x-=dyabs;
00409 px+=sdx;
00410 }
00411 py+=sdy;
00412 line.append(QPoint( px, py ));
00413 }
00414
00415 return line;
00416 }
00417
00418 QVPolyline::operator QVPolylineF() const
00419 {
00420 QVPolylineF polyline;
00421 foreach(QPoint point, *this)
00422 {
00423 polyline.append(QPointF(point));
00424 }
00425 return polyline;
00426 }
00427
00428
00430
00431
00432
00433
00434
00435
00436 #ifndef DOXYGEN_IGNORE_THIS
00437 const char coorX8Connect[8] = { 0, 1, 1, 1, 0, -1, -1, -1 };
00438 const char coorY8Connect[8] = { -1, -1, 0, 1, 1, 1, 0, -1 };
00439 const char coorX4Connect[4] = { 0, 1, 0, -1, };
00440 const char coorY4Connect[4] = { -1, 0, 1, 0, };
00441 const char coorX4Diag[8] = { 1, 1, -1, -1 };
00442 const char coorY4Diag[8] = { -1, 1, 1, -1 };
00443 #endif
00444
00445
00446 #ifndef DOXYGEN_IGNORE_THIS
00447 QVPolyline getConnectedSetBorderContourThresholdFromBorderPoint(const QVImage<uChar> &image, const int startPointX, const int startPointY, const uChar threshold)
00448 {
00449 QVPolyline lista;
00450
00451 lista.closed = true;
00452 lista.append(QPoint(startPointX, startPointY));
00453
00454 QVIMAGE_INIT_READ(uChar,image);
00455 QRect roi = image.getROI();
00456
00457 Q_ASSERT_X(roi.contains(startPointX, startPointY), "getContourThresholdFromBorderPoint", "start point out of image ROI");
00458 Q_ASSERT_X(QVIMAGE_PIXEL(image, startPointX, startPointY, 0) >= threshold, "getContourThresholdFromBorderPoint", "start point is not contained in a connected set");
00459
00460
00461
00462 uChar searchDir = 128, numOuterPixels = 0;
00463 for (int i = 0; i<8; i++)
00464 {
00465 int x = startPointX +coorX8Connect[i], y = startPointY +coorY8Connect[i];
00466 if (!roi.contains(x, y))
00467 {
00468 numOuterPixels++;
00469 searchDir = i;
00470 }
00471 else if (QVIMAGE_PIXEL(image, x, y,0) < threshold)
00472 {
00473 numOuterPixels++;
00474 searchDir = i;
00475 }
00476 }
00477
00478
00479 Q_ASSERT_X(searchDir < 8, "getContourThresholdFromBorderPoint", "start point is inside the set, not in the border");
00480
00481
00482 if (numOuterPixels == 8)
00483 return lista;
00484
00485
00486 int sumSearchDir = 0, actualPointX = startPointX, actualPointY = startPointY;
00487 while (true)
00488 {
00489
00490 uChar d;
00491 int nextPointX, nextPointY;
00492 for (d = 0; d < 8; d++)
00493 {
00494 searchDir = (searchDir+1)%8;
00495 nextPointX = actualPointX + coorX8Connect[searchDir];
00496 nextPointY = actualPointY + coorY8Connect[searchDir];
00497 if (roi.contains(nextPointX, nextPointY))
00498 if ( (QVIMAGE_PIXEL(image, nextPointX, nextPointY,0) >= threshold) )
00499 break;
00500 }
00501
00502 sumSearchDir += d - 3;
00503
00504 actualPointX = nextPointX;
00505 actualPointY = nextPointY;
00506
00507 if ( QVIMAGE_PIXEL(image, actualPointX, actualPointY,0) < threshold )
00508 break;
00509
00510 if ( startPointX == actualPointX && startPointY == actualPointY)
00511 break;
00512
00513 lista.append(QPoint(actualPointX, actualPointY));
00514 searchDir = searchDir + 4;
00515 }
00516
00517 lista.direction = (sumSearchDir >= 0);
00518 return lista;
00519 }
00520 #endif
00521
00522 QVPolyline getConnectedSetBorderContourThreshold(const QVImage<uChar> &image, const QPoint startPoint, const uChar threshold)
00523 {
00524 QVIMAGE_INIT_READ(uChar,image);
00525 const QRect roi = image.getROI();
00526
00527 int col = startPoint.x(), row = startPoint.y();
00528
00529 if (QVIMAGE_PIXEL(image, col, row,0) < threshold)
00530 return QVPolyline();
00531
00532 while (roi.contains(col+1, row))
00533 {
00534 if ( QVIMAGE_PIXEL(image, col+1, row,0) < threshold )
00535 break;
00536 col++;
00537 }
00538
00539 return getConnectedSetBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00540 }
00541
00542 QList<QVPolyline> getConnectedSetBorderContoursThreshold(const QVImage <uChar> &image, const uChar threshold)
00543 {
00544 qDebug() << "getPolylinesThreshold()";
00545 QVImage<uChar> mask(image.getCols()+1, image.getRows()+1);
00546 Set(mask,0);
00547
00548 QVIMAGE_INIT_READ(uChar,image);
00549 QVIMAGE_INIT_WRITE(uChar,mask);
00550
00551 const QRect roi = image.getROI();
00552
00553 QList<QVPolyline> polylineList;
00554
00555
00556 for (int row = roi.y(); row < roi.y() + roi.height(); row++)
00557 for (int col = roi.x(); col < roi.y() + roi.width(); col++)
00558 {
00559
00560 if (QVIMAGE_PIXEL(image, col, row,0) >= threshold)
00561 {
00562
00563 if ( !QVIMAGE_PIXEL(mask, col, row,0) )
00564 {
00565 QVPolyline lista = getConnectedSetBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00566 polylineList.append(lista);
00567
00568 QListIterator<QPoint> iterator(lista);
00569 for (QPoint previous = iterator.next(), actual; iterator.hasNext(); previous = actual)
00570 {
00571 actual = iterator.next();
00572 foreach (QPoint point, QVPolyline::line(actual.x(), actual.y(), previous.x(), previous.y()))
00573 QVIMAGE_PIXEL(mask, point.x(), point.y(),0) = true;
00574 }
00575 }
00576
00577
00578 while (roi.contains(col+1, row))
00579 {
00580 if ( QVIMAGE_PIXEL(image, col+1, row,0) < threshold )
00581 break;
00582 col++;
00583 }
00584
00585
00586 if ( !QVIMAGE_PIXEL(mask, col, row,0) )
00587 {
00588 QVPolyline lista = getConnectedSetBorderContourThresholdFromBorderPoint(image, col, row, threshold);
00589 polylineList.append(lista);
00590
00591 QListIterator<QPoint> iterator(lista);
00592 for (QPoint previous = iterator.next(), actual; iterator.hasNext(); previous = actual)
00593 {
00594 actual = iterator.next();
00595 foreach (QPoint point, QVPolyline::line(actual.x(), actual.y(), previous.x(), previous.y()))
00596 QVIMAGE_PIXEL(mask, point.x(), point.y(),0) = true;
00597 }
00598 }
00599 }
00600
00601 }
00602 qDebug() << "getPolylinesThreshold():"<< polylineList.size() << "contours obtained";
00603 qDebug() << "getPolylinesThreshold() <~ return";
00604 return polylineList;
00605 }
00606
00608
00609 QVPolyline getLineContourThreshold4Connectivity(QVImage<uChar> &image, const QPoint point, QVPolyline &polyline, const uChar threshold, bool reverse)
00610 {
00611 const uInt cols = image.getCols(), rows = image.getRows();
00612 QVIMAGE_INIT_WRITE(uChar, image);
00613
00614 uInt lastDir = 666, coorX = point.x(), coorY = point.y();
00615
00616 qDebug() << "\tContour: new contour";
00617
00618 forever {
00619 qDebug() << "\tContour:\tAppending point (" << coorX << ", " << coorY << ")";
00620 if (reverse)
00621 polyline.prepend(QPoint(coorX, coorY));
00622 else
00623 polyline.append(QPoint(coorX, coorY));
00624
00625 QVIMAGE_PIXEL(image, coorX, coorY, 0) = 0;
00626
00627 uInt dir;
00628 int newCoorX, newCoorY;
00629 for (dir = 0; dir < 4; dir++)
00630 {
00631 newCoorX = coorX + coorX4Connect[dir];
00632 newCoorY = coorY + coorY4Connect[dir];
00633
00634
00635 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00636 continue;
00637
00638
00639 if ( (QVIMAGE_PIXEL(image, newCoorX, newCoorY, 0) >= threshold) && (lastDir != dir) )
00640 break;
00641 }
00642
00643 if (dir == 4) break;
00644
00645 coorX = newCoorX;
00646 coorY = newCoorY;
00647 lastDir = (dir+2)%4;
00648 }
00649
00650 return polyline;
00651 }
00652
00653 QList<QVPolyline> getLineContoursThreshold4Connectivity(const QVImage<uChar> &image, const uChar threshold)
00654 {
00655 const uInt cols = image.getCols(), rows = image.getRows();
00656 QVImage<uChar> clone = image;
00657
00658 QList<QVPolyline> polylineList;
00659
00660
00661 for(uInt col = 0; col < cols; col++)
00662 for(uInt row = 0; row < rows; row++)
00663 {
00664 QVIMAGE_INIT_READ(uChar, clone);
00665
00666 if ( (QVIMAGE_PIXEL(clone, col, row, 0) < threshold) )
00667 continue;
00668
00669
00670 QVPolyline polyline;
00671
00672
00673 getLineContourThreshold4Connectivity(clone, QPoint(col, row), polyline, threshold, false);
00674
00675
00676 uInt dir;
00677 int newCoorX, newCoorY;
00678 for (dir = 0; dir < 4; dir++)
00679 {
00680 newCoorX = col + coorX4Connect[dir];
00681 newCoorY = row + coorY4Connect[dir];
00682
00683
00684 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00685 continue;
00686
00687
00688 if ( (clone(newCoorX, newCoorY) >= threshold) )
00689 break;
00690 }
00691
00692
00693 if (dir != 4)
00694 getLineContourThreshold4Connectivity(clone, QPoint(newCoorX, newCoorY), polyline, threshold, true);
00695
00696
00697 polylineList.append(polyline);
00698 }
00699
00700 return polylineList;
00701 }
00702
00704
00705 QVPolyline getLineContourThreshold8Connectivity(QVImage<uChar> &image, const QPoint point, QVPolyline &polyline, const uChar threshold, bool reverse)
00706 {
00707 const uInt cols = image.getCols(), rows = image.getRows();
00708 QVIMAGE_INIT_WRITE(uChar, image);
00709
00710 uInt lastDir = 666, coorX = point.x(), coorY = point.y();
00711
00712 qDebug() << "\tContour: new contour";
00713
00714 bool continueCond = true;
00715 while(continueCond)
00716 {
00717 qDebug() << "\tContour:\tAppending point (" << coorX << ", " << coorY << ")";
00718 if (reverse)
00719 polyline.prepend(QPoint(coorX, coorY));
00720 else
00721 polyline.append(QPoint(coorX, coorY));
00722
00723 QVIMAGE_PIXEL(image, coorX, coorY, 0) = 0;
00724
00725
00726 uInt dir;
00727 int newCoorX, newCoorY;
00728 for (dir = 0; dir < 4; dir++)
00729 {
00730 newCoorX = coorX + coorX4Connect[dir];
00731 newCoorY = coorY + coorY4Connect[dir];
00732
00733
00734 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00735 continue;
00736
00737
00738 if ( (QVIMAGE_PIXEL(image, newCoorX, newCoorY, 0) >= threshold) && (lastDir != dir) )
00739 break;
00740 }
00741
00742 if (dir == 4)
00743 {
00744
00745 uInt dir;
00746 int newCoorX, newCoorY;
00747 for (dir = 0; dir < 4; dir++)
00748 {
00749 newCoorX = coorX + coorX4Diag[dir];
00750 newCoorY = coorY + coorY4Diag[dir];
00751
00752
00753 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00754 continue;
00755
00756
00757 if ( (QVIMAGE_PIXEL(image, newCoorX, newCoorY, 0) >= threshold) && (lastDir != dir) )
00758 break;
00759 }
00760 if (dir == 4) break;
00761
00762 coorX = newCoorX;
00763 coorY = newCoorY;
00764 lastDir = (dir+2)%4;
00765 }
00766 else {
00767 coorX = newCoorX;
00768 coorY = newCoorY;
00769 lastDir = (dir+2)%4;
00770 }
00771 }
00772
00773 return polyline;
00774 }
00775
00776 QList<QVPolyline> getLineContoursThreshold8Connectivity(const QVImage<uChar> &image, const uChar threshold)
00777 {
00778 const uInt cols = image.getCols(), rows = image.getRows();
00779 QVImage<uChar> clone = image;
00780
00781 QList<QVPolyline> polylineList;
00782
00783
00784 for(uInt col = 0; col < cols; col++)
00785 for(uInt row = 0; row < rows; row++)
00786 {
00787 QVIMAGE_INIT_READ(uChar, clone);
00788
00789 if ( (QVIMAGE_PIXEL(clone, col, row, 0) < threshold) )
00790 continue;
00791
00792
00793 QVPolyline polyline;
00794
00795
00796 getLineContourThreshold8Connectivity(clone, QPoint(col, row), polyline, threshold, false);
00797
00798
00799 uInt dir;
00800 int newCoorX, newCoorY;
00801 for (dir = 0; dir < 4; dir++)
00802 {
00803 newCoorX = col + coorX4Connect[dir];
00804 newCoorY = row + coorY4Connect[dir];
00805
00806
00807 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00808 continue;
00809
00810
00811 if ( (clone(newCoorX, newCoorY) >= threshold) )
00812 break;
00813 }
00814
00815
00816 if (dir != 4)
00817 getLineContourThreshold8Connectivity(clone, QPoint(newCoorX, newCoorY), polyline, threshold, true);
00818 else {
00819
00820 uInt dir;
00821 int newCoorX, newCoorY;
00822 for (dir = 0; dir < 4; dir++)
00823 {
00824 newCoorX = col + coorX4Diag[dir];
00825 newCoorY = row + coorY4Diag[dir];
00826
00827
00828 if ( (newCoorX < 0) || (newCoorY < 0) || (newCoorX >= cols) || (newCoorY >= rows) )
00829 continue;
00830
00831
00832 if ( (clone(newCoorX, newCoorY) >= threshold) )
00833 break;
00834 }
00835
00836
00837 if (dir != 4)
00838 getLineContourThreshold8Connectivity(clone, QPoint(newCoorX, newCoorY), polyline, threshold, true);
00839 }
00840
00841
00842 polylineList.append(polyline);
00843 }
00844
00845 return polylineList;
00846 }