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