00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #include <string>
00043
00044 #include <algorithm>
00045 #include <cstdlib>
00046
00047 #include <qgarlib/GenPointChain.H>
00048 #include <qgarlib/LabeledSkeletonImage.H>
00049 #include <qgarlib/LinkedChainList.H>
00050 #include <qgarlib/QgarErrorDeveloper.H>
00051
00052
00053
00054 using namespace std;
00055
00056
00057 namespace qgar
00058 {
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 const unsigned char LINKEDCHAINLIST_MARK = 2;
00069
00070
00071 static int LINKEDCHAINLIST_MINL = 0;
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 int
00084 LINKEDCHAINLIST_connect4(unsigned char* p, int w)
00085 {
00086 return (*(p - w) == 255)
00087 + (*(p + w) == 255)
00088 + (*(p - 1) == 255)
00089 + (*(p + 1) == 255);
00090 }
00091
00092
00093
00094 int
00095 LINKEDCHAINLIST_connect4M(unsigned char* p, int w)
00096 {
00097 return (*(p - w) == LINKEDCHAINLIST_MARK)
00098 + (*(p + w) == LINKEDCHAINLIST_MARK)
00099 + (*(p - 1) == LINKEDCHAINLIST_MARK)
00100 + (*(p + 1) == LINKEDCHAINLIST_MARK);
00101 }
00102
00103
00104
00105 int
00106 LINKEDCHAINLIST_connect8(unsigned char* p, int w)
00107 {
00108 return (*(p - w - 1) == 255)
00109 + (*(p - w + 1) == 255)
00110 + (*(p + w - 1) == 255)
00111 + (*(p + w + 1) == 255);
00112 }
00113
00114
00115
00116 int
00117 LINKEDCHAINLIST_connect8M(unsigned char* p, int w)
00118 {
00119 return (*(p - w - 1) == LINKEDCHAINLIST_MARK)
00120 + (*(p - w + 1) == LINKEDCHAINLIST_MARK)
00121 + (*(p + w - 1) == LINKEDCHAINLIST_MARK)
00122 + (*(p + w + 1) == LINKEDCHAINLIST_MARK);
00123 }
00124
00125
00126
00127 Point
00128 LINKEDCHAINLIST_neigh(unsigned char* p, int l, int c, int w)
00129 {
00130 int x = c;
00131 int y = l;
00132
00133 if (*(p + 1) == 255)
00134 {
00135 x += 1;
00136 }
00137 else if (*(p + w) == 255)
00138 {
00139 y += 1;
00140 }
00141 else if (*(p - 1) == 255)
00142 {
00143 x -= 1;
00144 }
00145 else if (*(p - w) == 255)
00146 {
00147 y -= 1;
00148 }
00149 else if (*(p + w + 1) == 255)
00150 {
00151 x += 1;
00152 y += 1;
00153 }
00154 else if (*(p + w - 1) == 255)
00155 {
00156 x -= 1;
00157 y += 1;
00158 }
00159 else if (*(p - w - 1) == 255)
00160 {
00161 x -= 1;
00162 y -= 1;
00163 }
00164 else if (*(p - w + 1) == 255)
00165 {
00166 x += 1;
00167 y -= 1;
00168 }
00169
00170
00171
00172
00173
00174 return Point(x,y);
00175 }
00176
00177
00178
00179
00180
00181 Point
00182 LINKEDCHAINLIST_neighPlus(unsigned char* p, int l, int c, int w)
00183 {
00184 int x = c;
00185 int y = l;
00186
00187 if (*(p + 1) != 0)
00188 {
00189 x += 1;
00190 }
00191 else if (*(p + w) != 0)
00192 {
00193 y += 1;
00194 }
00195 else if (*(p - 1) != 0)
00196 {
00197 x -= 1;
00198 }
00199 else if (*(p - w) != 0)
00200 {
00201 y -= 1;
00202 }
00203 else if (*(p + w + 1) != 0)
00204 {
00205 x += 1;
00206 y += 1;
00207 }
00208 else if (*(p + w - 1) != 0)
00209 {
00210 x -= 1;
00211 y += 1;
00212 }
00213 else if (*(p - w - 1) != 0)
00214 {
00215 x -= 1;
00216 y -= 1;
00217 }
00218 else if (*(p - w + 1) != 0)
00219 {
00220 x += 1;
00221 y -= 1;
00222 }
00223
00224
00225
00226
00227
00228 return Point(x,y);
00229 }
00230
00231
00232
00233 Point
00234 LINKEDCHAINLIST_neigh4(unsigned char* p, int l, int c, int w)
00235 {
00236 int x = c;
00237 int y = l;
00238
00239 if (*(p + 1) == 255)
00240 {
00241 x += 1;
00242 }
00243 else if (*(p + w) == 255)
00244 {
00245 y += 1;
00246 }
00247 else if (*(p - 1) == 255)
00248 {
00249 x -= 1;
00250 }
00251 else if (*(p - w) == 255)
00252 {
00253 y -= 1;
00254 }
00255
00256
00257
00258
00259
00260 return Point(x,y);
00261 }
00262
00263
00264
00265 Point
00266 LINKEDCHAINLIST_neigh8(unsigned char* p, int l, int c, int w)
00267 {
00268 int x = c;
00269 int y = l;
00270
00271 if (*(p + w + 1) == 255)
00272 {
00273 x += 1;
00274 y += 1;
00275 }
00276 else if (*(p + w - 1) == 255)
00277 {
00278 x -= 1;
00279 y += 1;
00280 }
00281 else if (*(p - w - 1) == 255)
00282 {
00283 x -= 1;
00284 y -= 1;
00285 }
00286 else if (*(p - w + 1) == 255)
00287 {
00288 x += 1;
00289 y -= 1;
00290 }
00291
00292
00293
00294
00295
00296 return Point(x,y);
00297 }
00298
00299
00300
00301 Point
00302 LINKEDCHAINLIST_neighM(unsigned char* p, int l, int c, int w)
00303 {
00304 int x = c;
00305 int y = l;
00306
00307 if (*(p + 1) == LINKEDCHAINLIST_MARK)
00308 {
00309 x += 1;
00310 }
00311 else if (*(p + w) == LINKEDCHAINLIST_MARK)
00312 {
00313 y += 1;
00314 }
00315 else if (*(p - 1) == LINKEDCHAINLIST_MARK)
00316 {
00317 x -= 1;
00318 }
00319 else if (*(p - w) == LINKEDCHAINLIST_MARK)
00320 {
00321 y -= 1;
00322 }
00323 else if (*(p + w + 1) == LINKEDCHAINLIST_MARK)
00324 {
00325 x += 1;
00326 y += 1;
00327 }
00328 else if (*(p + w - 1) == LINKEDCHAINLIST_MARK)
00329 {
00330 x -= 1;
00331 y += 1;
00332 }
00333 else if (*(p - w - 1) == LINKEDCHAINLIST_MARK)
00334 {
00335 x -= 1;
00336 y -= 1;
00337 }
00338 else if (*(p - w + 1) == LINKEDCHAINLIST_MARK)
00339 {
00340 x += 1;
00341 y -= 1;
00342 }
00343
00344
00345
00346
00347
00348 return Point(x,y);
00349 }
00350
00351
00352
00353 Point
00354 LINKEDCHAINLIST_neigh4M(unsigned char* p, int l, int c, int w)
00355 {
00356 int x = c;
00357 int y = l;
00358
00359 if (*(p + 1) == LINKEDCHAINLIST_MARK)
00360 {
00361 x += 1;
00362 }
00363 else if (*(p + w) == LINKEDCHAINLIST_MARK)
00364 {
00365 y += 1;
00366 }
00367 else if (*(p - 1) == LINKEDCHAINLIST_MARK)
00368 {
00369 x -= 1;
00370 }
00371 else if (*(p - w) == LINKEDCHAINLIST_MARK)
00372 {
00373 y -= 1;
00374 }
00375
00376
00377
00378
00379
00380 return Point(x,y);
00381 }
00382
00383
00384
00385 Point
00386 LINKEDCHAINLIST_neigh8M(unsigned char* p, int l, int c, int w)
00387 {
00388 int x = c;
00389 int y = l;
00390
00391 if (*(p + w + 1) == LINKEDCHAINLIST_MARK)
00392 {
00393 x += 1;
00394 y += 1;
00395 }
00396 else if (*(p + w - 1) == LINKEDCHAINLIST_MARK)
00397 {
00398 x -= 1;
00399 y += 1;
00400 }
00401 else if (*(p - w - 1) == LINKEDCHAINLIST_MARK)
00402 {
00403 x -= 1;
00404 y -= 1;
00405 }
00406 else if (*(p - w + 1) == LINKEDCHAINLIST_MARK)
00407 {
00408 x += 1;
00409 y -= 1;
00410 }
00411
00412
00413
00414
00415
00416 return Point(x,y);
00417 }
00418
00419
00420
00421 void
00422 LINKEDCHAINLIST_markNeigh(unsigned char* p, int w, int c4, int c8)
00423 {
00424 if (c4 != 0 && c8 == 0)
00425 {
00426
00427 if (*(p + 1) != 0)
00428 {
00429 *(p + 1) = LINKEDCHAINLIST_MARK;
00430 }
00431
00432 if (*(p + w) != 0)
00433 {
00434 *(p + w) = LINKEDCHAINLIST_MARK;
00435 }
00436
00437 if (*(p - 1) != 0)
00438 {
00439 *(p - 1) = LINKEDCHAINLIST_MARK;
00440 }
00441
00442 if (*(p - w) != 0)
00443 {
00444 *(p - w) = LINKEDCHAINLIST_MARK;
00445 }
00446 }
00447 else if (c4 == 0 && c8 != 0)
00448 {
00449
00450 if (*(p + w + 1) != 0)
00451 {
00452 *(p + w + 1) = LINKEDCHAINLIST_MARK;
00453 }
00454
00455 if (*(p + w - 1) != 0)
00456 {
00457 *(p + w - 1) = LINKEDCHAINLIST_MARK;
00458 }
00459
00460 if (*(p - w - 1) != 0)
00461 {
00462 *(p - w - 1) = LINKEDCHAINLIST_MARK;
00463 }
00464
00465 if (*(p - w + 1) != 0)
00466 {
00467 *(p - w + 1) = LINKEDCHAINLIST_MARK;
00468 }
00469 }
00470 else
00471 {
00472
00473
00474 if (*(p + 1) != 0)
00475 {
00476 *(p + 1) = LINKEDCHAINLIST_MARK;
00477 }
00478
00479 if (*(p + w) != 0)
00480 {
00481 *(p + w) = LINKEDCHAINLIST_MARK;
00482 }
00483
00484 if (*(p - 1) != 0)
00485 {
00486 *(p - 1) = LINKEDCHAINLIST_MARK;
00487 }
00488
00489 if (*(p - w) != 0)
00490 {
00491 *(p - w) = LINKEDCHAINLIST_MARK;
00492 }
00493
00494
00495 if ((*(p + w + 1) != 0) && (*(p + 1) == 0) && (*(p + w) == 0))
00496 {
00497 *(p + w + 1) = LINKEDCHAINLIST_MARK;
00498 }
00499
00500 if ((*(p + w - 1) != 0) && (*(p + w) == 0) && (*(p - 1) == 0))
00501 {
00502 *(p + w - 1) = LINKEDCHAINLIST_MARK;
00503 }
00504
00505 if ((*(p - w - 1) != 0) && (*(p - 1) == 0) && (*(p - w) == 0))
00506 {
00507 *(p - w - 1) = LINKEDCHAINLIST_MARK;
00508 }
00509
00510 if ((*(p - w + 1) != 0) && (*(p - w) == 0) && (*(p + 1) == 0))
00511 {
00512 *(p - w + 1) = LINKEDCHAINLIST_MARK;
00513 }
00514 }
00515 }
00516
00517
00518
00519 int
00520 LINKEDCHAINLIST_degree(unsigned char* p, int w)
00521 {
00522 int d = 0;
00523
00524 if((*(p-1)) != 0)
00525 {
00526 ++d;
00527 }
00528
00529 if((*(p-w-1)) != 0)
00530 {
00531 ++d;
00532 }
00533
00534 if((*(p-w)) != 0)
00535 {
00536 ++d;
00537 }
00538
00539 if((*(p-w+1)) != 0)
00540 {
00541 ++d;
00542 }
00543
00544 if((*(p+1)) != 0)
00545 {
00546 ++d;
00547 }
00548
00549 if((*(p+w+1)) != 0)
00550 {
00551 ++d;
00552 }
00553
00554 if((*(p+w)) != 0)
00555 {
00556 ++d;
00557 }
00558
00559 if((*(p+w-1)) != 0)
00560 {
00561 ++d;
00562 }
00563
00564 return d;
00565 }
00566
00567
00568
00569 void
00570 LINKEDCHAINLIST_loadBinNeigh(unsigned char* p, unsigned char* n, int w)
00571 {
00572 *n = *p ? 1 : 0;
00573 ++n;
00574 *n = *(p-1) ? 1 : 0;
00575 ++n;
00576 *n = *(p - w - 1) ? 1 : 0;
00577 ++n;
00578 *n = *(p - w) ? 1 : 0;
00579 ++n;
00580 *n = *(p - w + 1) ? 1 : 0;
00581 ++n;
00582 *n = *(p + 1) ? 1 : 0;
00583 ++n;
00584 *n = *(p + w + 1) ? 1 : 0;
00585 ++n;
00586 *n = *(p + w) ? 1 : 0;
00587 ++n;
00588 *n = *(p + w - 1) ? 1 : 0;
00589 ++n;
00590 *n = *(p - 1) ? 1 : 0;
00591 }
00592
00593
00594
00595 int
00596 LINKEDCHAINLIST_crossNb(unsigned char* n, int w)
00597 {
00598 int x4=0;
00599
00600 for(int k = 1 ; k <= 8 ; ++k)
00601 {
00602 x4 += std::abs(n[k + 1] - n[k]);
00603 }
00604
00605 x4 /= 2;
00606
00607 return x4;
00608 }
00609
00610
00611
00612
00613
00614 static bool
00615 LINKEDCHAINLIST_tooSmall(PointChain& xChain)
00616 {
00617 return (xChain.size() < LINKEDCHAINLIST_MINL);
00618 }
00619
00620
00621
00622
00623
00624 bool
00625 LINKEDCHAINLIST_areNeigh(Point p1, Point p2)
00626 {
00627 return (std::fabs((double)p1.x() - p2.x()) <= 1)
00628 && (std::fabs((double)p1.y() - p2.y()) <= 1);
00629 }
00630
00631
00632
00633
00634
00635 int
00636 LINKEDCHAINLIST_canMerge(PointChain& ch1, PointChain& ch2)
00637 {
00638 return LINKEDCHAINLIST_areNeigh(ch1.back(), ch2.front())
00639 || LINKEDCHAINLIST_areNeigh(ch1.front(), ch2.back())
00640 || LINKEDCHAINLIST_areNeigh(ch1.front(), ch2.front())
00641 || LINKEDCHAINLIST_areNeigh(ch1.back(), ch2.back());
00642 }
00643
00644
00645
00646 void
00647 LINKEDCHAINLIST_mergeChains(PointChain& ch1, PointChain& ch2)
00648 {
00649 if (LINKEDCHAINLIST_areNeigh(ch1.front(), ch2.front()))
00650 {
00651 ch1.reverse();
00652 }
00653 else if (LINKEDCHAINLIST_areNeigh(ch1.back(), ch2.back()))
00654 {
00655 ch1.reverse();
00656 }
00657
00658 if (LINKEDCHAINLIST_areNeigh(ch1.back(), ch2.front()))
00659 {
00660 (ch1.pointList()).insert(ch1.pointList().end(),
00661 ch2.pointList().begin(),
00662 ch2.pointList().end());
00663 }
00664
00665
00666 else if (LINKEDCHAINLIST_areNeigh(ch1.front(), ch2.back()))
00667 {
00668 (ch1.pointList()).insert(ch1.pointList().begin(),
00669 ch2.pointList().begin(),
00670 ch2.pointList().end());
00671 }
00672
00673
00674
00675
00676
00677 }
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697 LinkedChainList::LinkedChainList(const BinaryImage& img,
00698 unsigned int minChainLength,
00699 unsigned int minCycleLength)
00700
00701 : _minChainLength(minChainLength),
00702 _minCycleLength(minCycleLength)
00703
00704 {
00705
00706 GreyLevelImage wkImg(img);
00707
00708
00709 LINKEDCHAINLIST_MINL = minChainLength;
00710
00711
00712 GreyLevelImage::value_type* pixmap = wkImg.pPixMap();
00713 int width = img.width();
00714 int height = img.height();
00715
00716
00717 GreyLevelImage::value_type* p = pixmap;
00718 for (int i = 0; i < width ; ++i)
00719 {
00720 *p = 0;
00721 ++p;
00722 }
00723
00724 p = pixmap;
00725 for (int i = 0 ; i < height ; ++i, p += width)
00726 {
00727 *p = 0;
00728 }
00729
00730 p = pixmap + width - 1;
00731 for (int i = 0 ; i < height ; ++i, p += width)
00732 {
00733 *p = 0;
00734 }
00735
00736 p = pixmap + (height - 1) * width;
00737 for (int i = 0 ; i < width ; ++i)
00738 {
00739 *p = 0;
00740 ++p;
00741 }
00742
00743 int i;
00744
00745 for (i = 1, p = pixmap + width + 1 ; i < (height - 1) ; ++i, p += 2)
00746 for (int j = 1 ; j < (width - 1) ; ++j, ++p)
00747 if (*p != 0)
00748 {
00749 int c4 = LINKEDCHAINLIST_connect4(p, width);
00750 int c8 = LINKEDCHAINLIST_connect8(p, width);
00751
00752 if ((c4 == 0) && (c8 == 0))
00753 {
00754
00755 *p = 0;
00756 }
00757 else if ((c4 + c8) == 1)
00758 {
00759
00760 PointChain* ch1 = new PointChain;
00761 ch1 = aChain(ch1, i, j, wkImg);
00762
00763 if (ch1 != 0)
00764 {
00765 if (ch1->size() < _minChainLength)
00766 {
00767 delete ch1;
00768 }
00769 else
00770 {
00771 push_back(*ch1);
00772 }
00773 }
00774 }
00775 else
00776 {
00777
00778
00779 PointChain* ch1 = new PointChain;
00780
00781 ch1 = aChain(ch1, i, j, wkImg);
00782
00783
00784
00785 if ((LINKEDCHAINLIST_connect4(p, width) +
00786 LINKEDCHAINLIST_connect8(p, width)) != 0)
00787 {
00788
00789 Point v = LINKEDCHAINLIST_neigh(p, i, j, width);
00790 PointChain* ch2 = new PointChain;
00791 ch2 = aChain(ch2, v.y(), v.x(), wkImg);
00792
00793 if ((ch1 != 0) && (ch2 != 0) && LINKEDCHAINLIST_canMerge(*ch1, *ch2))
00794 {
00795 LINKEDCHAINLIST_mergeChains(*ch1, *ch2);
00796 delete ch2;
00797 }
00798 else if (ch2 != 0)
00799 {
00800 if(ch2->size() < _minChainLength)
00801 {
00802 delete ch2;
00803 }
00804 else
00805 {
00806 push_back(*ch2);
00807 }
00808 }
00809 }
00810
00811 if (ch1 != 0)
00812 {
00813 if(ch1->size() < _minChainLength)
00814 {
00815 delete ch1;
00816 }
00817 else
00818 {
00819 push_back(*ch1);
00820 }
00821 }
00822 }
00823
00824 }
00825 }
00826
00827
00828
00829
00830
00831
00832
00833 LinkedChainList::LinkedChainList(const LabeledSkeletonImage& skel)
00834
00835 throw(QgarErrorDeveloper)
00836
00837 : _minChainLength(0),
00838 _minCycleLength(0)
00839
00840 {
00841
00842 GreyLevelImage wkImg(skel);
00843
00844
00845 GreyLevelImage::value_type* pixmap = wkImg.pPixMap();
00846 int width = skel.width();
00847 int height = skel.height();
00848
00849 int i = 0;
00850 GreyLevelImage::value_type* p = pixmap;
00851
00852 GreyLevelImage::value_type n[10];
00853
00854
00855
00856 for (i = 1, p = pixmap + width + 1 ; i < height - 1 ; ++i, p += 2)
00857 for (int j = 1 ; j < width - 1 ; ++j, ++p)
00858 if (*p != 0)
00859 {
00860 LINKEDCHAINLIST_loadBinNeigh(p, n, width);
00861
00862 if (((*(p-width) != 0) && (*(p-width+1) != 0) && (*(p+1) != 0)) ||
00863 ((*(p+1) != 0) && (*(p+width+1) != 0) && (*(p+width) != 0)) ||
00864 ((*(p+width) != 0) && (*(p+width-1) != 0) && (*(p-1) != 0)) ||
00865 ((*(p-1) != 0) && (*(p-width-1) != 0) && (*(p-width) != 0)))
00866 {
00867 *p = LINKEDCHAINLIST_MARK;
00868 }
00869 else if (LINKEDCHAINLIST_crossNb(n, width) == 2)
00870 {
00871 *p = 255;
00872 }
00873 else
00874 {
00875 *p = LINKEDCHAINLIST_MARK;
00876 }
00877 }
00878
00879 int encore = 1;
00880
00881
00882 while (encore)
00883 {
00884 for (i = 1, p = pixmap + width + 1 ; i < height - 1 ; ++i, p += 2)
00885 for (int j = 1 ; j < width - 1 ; ++j, ++p)
00886 if (*p == LINKEDCHAINLIST_MARK)
00887 {
00888 int d = LINKEDCHAINLIST_degree(p, width);
00889
00890 if (d == 0)
00891
00892 *p = 0;
00893 else
00894 {
00895
00896 Point fPoint(j, i);
00897
00898
00899 list<Point> pList;
00900
00901 if(*(p+1) != 0)
00902 {
00903 Point aPoint = fPoint;
00904 aPoint.translate(1, 0);
00905 pList.push_back(aPoint);
00906 *(p+1) -= 1;
00907 }
00908
00909 if(*(p+width) != 0)
00910 {
00911 Point aPoint = fPoint;
00912 aPoint.translate(0, 1);
00913 pList.push_back(aPoint);
00914 *(p+width) -= 1;
00915 }
00916
00917 if(*(p-1) != 0)
00918 {
00919 Point aPoint = fPoint;
00920 aPoint.translate(-1, 0);
00921 pList.push_back(aPoint);
00922 *(p-1) -= 1;
00923 }
00924
00925 if(*(p-width) != 0)
00926 {
00927 Point aPoint = fPoint;
00928 aPoint.translate(0, -1);
00929 pList.push_back(aPoint);
00930 *(p-width) -= 1;
00931 }
00932
00933 if(*(p+width+1) != 0 && *(p+1) == 0 && *(p+width) == 0)
00934 {
00935 Point aPoint = fPoint;
00936 aPoint.translate(1, 1);
00937 pList.push_back(aPoint);
00938 *(p+width+1) -= 1;
00939 }
00940
00941 if(*(p+width-1) != 0 && *(p+width) == 0 && *(p-1) == 0)
00942 {
00943 Point aPoint = fPoint;
00944 aPoint.translate(-1, 1);
00945 pList.push_back(aPoint);
00946 *(p+width-1) -= 1;
00947 }
00948
00949 if(*(p-width-1) !=0 && *(p-1) == 0 && *(p-width) == 0)
00950 {
00951 Point aPoint = fPoint;
00952 aPoint.translate(-1, -1);
00953 pList.push_back(aPoint);
00954 *(p-width-1) -= 1;
00955 }
00956
00957 if(*(p-width+1) != 0 && *(p-width) == 0 && *(p+1) == 0)
00958 {
00959 Point aPoint = fPoint;
00960 aPoint.translate(1, -1);
00961 pList.push_back(aPoint);
00962 *(p-width+1) -= 1;
00963 }
00964
00965 list<Point>::iterator myIter = pList.begin();
00966
00967 while (myIter != pList.end())
00968 {
00969 Point cPoint = fPoint;
00970
00971 PointChain* ch = new PointChain;
00972 ch->push_back(cPoint);
00973
00974
00975 *p = 0;
00976
00977 cPoint = *myIter;
00978 ch->push_back(cPoint);
00979 GreyLevelImage::value_type* pp = pixmap + cPoint.y() * width + cPoint.x();
00980
00981
00982
00983 if (*pp == 0)
00984 {
00985 delete ch;
00986 ++myIter;
00987 continue;
00988 }
00989
00990
00991 *pp += 1;
00992
00993 int continueChain = 1;
00994
00995 if (*pp == LINKEDCHAINLIST_MARK)
00996 continueChain = 0;
00997 else
00998 *pp = 0;
00999
01000 while (continueChain)
01001 {
01002 int checkLoop = 0;
01003
01004 Point nPoint = LINKEDCHAINLIST_neigh4(pp, cPoint.y(), cPoint.x(), width);
01005
01006 if (nPoint == cPoint)
01007 {
01008
01009 nPoint = LINKEDCHAINLIST_neigh4M(pp, cPoint.y(), cPoint.x(), width);
01010
01011 if (nPoint == cPoint)
01012 {
01013
01014
01015 nPoint = LINKEDCHAINLIST_neigh8(pp, cPoint.y(),
01016 cPoint.x(), width);
01017
01018 if (nPoint == cPoint)
01019 {
01020
01021 nPoint = LINKEDCHAINLIST_neigh8M(pp,
01022 cPoint.y(),
01023 cPoint.x(),
01024 width);
01025
01026 if (nPoint == cPoint)
01027
01028 {
01029
01030 nPoint = LINKEDCHAINLIST_neighPlus(pp, cPoint.y(), cPoint.x(), width);
01031
01032 if (nPoint == cPoint)
01033 {
01034
01035 throw QgarErrorDeveloper(__FILE__, __LINE__,
01036 "qgar::LinkedChainList::LinkedChainList(const qgar::LabeledSkeletonImage&)",
01037 "Strange things happen: See Karl!");
01038 }
01039 else
01040 checkLoop = 1;
01041
01042 continueChain = 0;
01043 }
01044 else
01045 continueChain = 0;
01046 }
01047 }
01048 else
01049 continueChain = 0;
01050 }
01051
01052
01053 cPoint = nPoint;
01054
01055
01056 ch->push_back(cPoint);
01057
01058
01059 pp = pixmap + cPoint.y() * width + cPoint.x();
01060
01061
01062 if (continueChain)
01063 *pp = 0;
01064 else if (checkLoop)
01065 {
01066
01067
01068
01069
01070 if (*pp != (LINKEDCHAINLIST_MARK - 1))
01071 {
01072
01073 ch->push_back(fPoint);
01074
01075 *pp = 0;
01076 }
01077 }
01078 }
01079
01080
01081 push_back(*ch);
01082
01083
01084 *p = LINKEDCHAINLIST_MARK;
01085
01086
01087 ++myIter;
01088 }
01089
01090
01091 *p = 0;
01092 }
01093
01094 }
01095
01096
01097 encore = 0;
01098
01099 for (i = 1, p = pixmap + width + 1 ;
01100 (encore == 0) && (i < height - 1) ;
01101 ++i, p += 2)
01102 {
01103 for (int j = 1 ; j < width - 1 ; ++j, ++p)
01104 {
01105 if (*p != 0)
01106 {
01107 *p = LINKEDCHAINLIST_MARK;
01108 encore = 1;
01109 break;
01110 }
01111 }
01112 }
01113 }
01114
01115 }
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125 LinkedChainList::LinkedChainList(unsigned int minChainLength,
01126 unsigned int minCycleLength)
01127
01128 : _minChainLength(minChainLength),
01129 _minCycleLength(minCycleLength)
01130
01131 {
01132
01133 }
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144 LinkedChainList::~LinkedChainList()
01145 {
01146 erase(begin(), end());
01147 }
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159 PointChain*
01160 LinkedChainList::aChain(PointChain* ch,
01161 int l,
01162 int c,
01163 GreyLevelImage& wkImg)
01164 {
01165
01166 GreyLevelImage::value_type* pixmap = wkImg.pPixMap();
01167 int width = wkImg.width();
01168
01169
01170 LinkedChainList tmpList(_minChainLength, _minCycleLength);
01171
01172
01173 Point cPoint(c, l);
01174 ch->push_back(cPoint);
01175
01176
01177 GreyLevelImage::value_type* p = pixmap + l * width + c;
01178 *p = 0;
01179 int c4 = LINKEDCHAINLIST_connect4(p, width);
01180 int c8 = LINKEDCHAINLIST_connect8(p, width);
01181
01182 if ((c4 == 0) && (c8 == 0))
01183 {
01184
01185
01186 if ((ch->size() >= _minCycleLength) &&
01187 (LINKEDCHAINLIST_connect4M(p, width) == 1) &&
01188 (LINKEDCHAINLIST_connect8M(p, width) == 0))
01189 {
01190 Point v = LINKEDCHAINLIST_neigh4M(p, l, c, width);
01191 ch->push_back(v);
01192 *(pixmap + v.y() * width + v.x()) = 0;
01193 }
01194 else if ((ch->size() >= _minCycleLength) &&
01195 (LINKEDCHAINLIST_connect8M(p, width) == 1) &&
01196 (LINKEDCHAINLIST_connect4M(p, width) == 0))
01197 {
01198 Point v = LINKEDCHAINLIST_neigh8M(p, l, c, width);
01199 ch->push_back(v);
01200 *(pixmap + v.y() * width + v.x()) = 0;
01201 }
01202
01203 return ch;
01204 }
01205
01206 else if ((c4 + c8) == 1)
01207 {
01208 Point v = LINKEDCHAINLIST_neigh(p, l, c, width);
01209
01210 return aChain(ch, v.y(), v.x(), wkImg);
01211 }
01212 else
01213 {
01214 LINKEDCHAINLIST_markNeigh(p, width, c4, c8);
01215
01216 while (LINKEDCHAINLIST_connect4M(p, width) +
01217 LINKEDCHAINLIST_connect8M(p, width) != 0)
01218 {
01219
01220
01221 Point v = LINKEDCHAINLIST_neighM(p, l, c, width);
01222 PointChain* tmpch = new PointChain;
01223 tmpch = aChain(tmpch, v.y(), v.x(), wkImg);
01224
01225 if (tmpch != 0)
01226 tmpList.push_back(*tmpch);
01227 }
01228
01229
01230 LinkedChainList::iterator newend =
01231 std::remove_if(tmpList.begin(), tmpList.end(), LINKEDCHAINLIST_tooSmall);
01232
01233
01234 tmpList.erase(newend, tmpList.end());
01235
01236
01237 if (tmpList.size() == 1 && LINKEDCHAINLIST_canMerge(*ch, tmpList.front()))
01238 {
01239 PointChain tmpChain = tmpList.front();
01240 tmpList.pop_front();
01241
01242
01243 LINKEDCHAINLIST_mergeChains(*ch, tmpChain);
01244
01245
01246 return ch;
01247 }
01248 else if (tmpList.size() > 1 && ch->size() == 1)
01249 {
01250 LinkedChainList::iterator tmpIter = tmpList.begin();
01251
01252 while (tmpIter != tmpList.end())
01253 if ((*tmpIter).size() > 0 &&
01254 LINKEDCHAINLIST_canMerge(*ch, *tmpIter))
01255 {
01256 LINKEDCHAINLIST_mergeChains(*tmpIter, *ch);
01257 delete ch;
01258 ch = 0;
01259 break;
01260 }
01261 else
01262 {
01263 ++tmpIter;
01264 }
01265 }
01266
01267
01268 insert(end(),tmpList.begin(),tmpList.end());
01269
01270 return ch;
01271 }
01272 }
01273
01274
01275
01276
01277 }