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