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 <vector>
00043
00044 #include <qgarlib/Dist34BlackCCImage.H>
00045 #include <qgarlib/GenImage.H>
00046 #include <qgarlib/LabeledSkeletonImage.H>
00047 #include <qgarlib/primitives.H>
00048
00049
00050
00051 using namespace std;
00052
00053
00054
00055 namespace qgar
00056 {
00057
00058
00059
00060
00061
00062
00063 LabeledSkeletonImage::LabeledSkeletonImage(const Dist34BlackCCImage& img,
00064 int maxPruning)
00065
00066 : GreyLevelImage(img)
00067
00068 {
00069 _pixMap2 = new GreyLevelImage::value_type[img.width() * img.height()];
00070 int pixsize = _width * _height;
00071 GreyLevelImage::value_type* newp = _pixMap2;
00072 int i = 0;
00073 int j = 0;
00074
00075
00076 for (i = 0 ; i < pixsize ; ++i, ++newp)
00077 {
00078 *newp = 255;
00079 }
00080
00081
00082
00083 GreyLevelImage::value_type* oldp = _pPixMap;
00084 for(i = 0 ; i < pixsize ; ++i, ++oldp)
00085 {
00086 if (*oldp == 3)
00087 {
00088 *oldp = 1;
00089 }
00090 if (*oldp == 6)
00091 {
00092 *oldp = 5;
00093 }
00094 }
00095
00096
00097 parallelSkelet();
00098
00099
00100 oldp=_pPixMap;
00101 for(i = 0 ; i < pixsize ; ++i, ++oldp)
00102 {
00103 if (*oldp == 1)
00104 {
00105 *oldp = 3;
00106 }
00107 if (*oldp == 5)
00108 {
00109 *oldp = 6;
00110 }
00111 }
00112
00113
00114 sequentSkelet();
00115
00116
00117
00118 newp = _pixMap2;
00119 for(i = 0 ; i < pixsize ; ++i, ++newp)
00120 {
00121 if (*newp == 1)
00122 {
00123 *newp = 0;
00124 }
00125 }
00126
00127
00128 finalThinning();
00129
00130
00131 if (maxPruning > 0)
00132 {
00133
00134
00135 vector<Point> myEndPoints;
00136 GreyLevelImage::value_type n[10];
00137
00138 for (i = 1 ; i < (_height - 1) ; ++i)
00139 {
00140 oldp = _pPixMap + (i * _width) + 1;
00141 newp = _pixMap2 + (i * _width) + 1;
00142
00143 for (j = 1 ; j < (_width - 1) ; ++j, ++newp)
00144 {
00145 if(*newp == 0)
00146 {
00147 loadBinaryNeighbors(newp, n);
00148 int x4=crossingCnt(n);
00149 if(x4 == 1)
00150 {
00151 Point endp(j, i);
00152 myEndPoints.push_back(endp);
00153 }
00154 }
00155 }
00156 }
00157
00158 pruning(myEndPoints, maxPruning);
00159 }
00160
00161
00162 removeJaggedness();
00163
00164
00165
00166 oldp = _pPixMap;
00167 newp = _pixMap2;
00168
00169 for (i = 0 ; i < pixsize ; ++i, ++oldp, ++newp)
00170 {
00171 if ((*oldp != 0) && (*newp != 0))
00172 {
00173 *oldp = 0;
00174 }
00175 }
00176
00177
00178 delete newp;
00179 }
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 LabeledSkeletonImage::~LabeledSkeletonImage()
00190 {
00191 if (_pixMap2 != 0)
00192 {
00193 delete [] _pixMap2;
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 void
00207 LabeledSkeletonImage::parallelSkelet()
00208 {
00209 GreyLevelImage::value_type lab[10];
00210 GreyLevelImage::value_type neighbors[10];
00211 GreyLevelImage::value_type suitbin[10];
00212
00213 GreyLevelImage::value_type* newp;
00214 GreyLevelImage::value_type* oldp;
00215
00216 for (int i = 1 ; i < (_height - 1) ; ++i)
00217 {
00218 oldp = _pPixMap + (i * _width) + 1;
00219 newp = _pixMap2 + (i * _width) + 1;
00220
00221 for(int j = 1 ; j < (_width - 1) ; ++j, ++newp, ++oldp)
00222 {
00223 if (*oldp != 0)
00224 {
00225
00226
00227 loadLabeledNeighbors(oldp,lab);
00228
00229 if ((lab[2] < (*oldp + 4)) && (lab[3] < (*oldp + 3)) &&
00230 (lab[4] < (*oldp + 4)) && (lab[1] < (*oldp + 3)) &&
00231 (lab[5] < (*oldp + 3)) && (lab[6] < (*oldp + 4)) &&
00232 (lab[7] < (*oldp + 3)) && (lab[8] < (*oldp + 4)))
00233 {
00234
00235
00236
00237 if (((lab[1] > *oldp) && (lab[2] > *oldp) && (lab[3] > *oldp)) ||
00238 ((lab[3] > *oldp) && (lab[4] > *oldp) && (lab[5] > *oldp)) ||
00239 ((lab[5] > *oldp) && (lab[6] > *oldp) && (lab[7] > *oldp)) ||
00240 ((lab[7] > *oldp) && (lab[8] > *oldp) && (lab[1] > *oldp)))
00241 {
00242 *newp = 255;
00243 }
00244 else
00245 {
00246 *newp = 0;
00247 }
00248 }
00249 else
00250 {
00251 loadLabeledNeighbors(oldp,neighbors);
00252 loadSuitCBinary(suitbin,neighbors);
00253 int c8 = connexityCnt(suitbin);
00254
00255
00256 loadSuitXBinary(suitbin,neighbors);
00257 int x4 = crossingCnt(suitbin);
00258
00259 if (*oldp != 1)
00260 {
00261 if ((c8 > 1) || (x4 > 1))
00262 {
00263 *newp = 0;
00264 }
00265 else
00266 {
00267 *newp = 255;
00268 }
00269 }
00270 else
00271 {
00272 if ((c8 > 1) || (x4 > 1) ||
00273 (oddEvenOddLab3(lab,1)==3) ||
00274 (oddEvenOddLab3(lab,3)==3) ||
00275 (oddEvenOddLab3(lab,5)==3) ||
00276 (oddEvenOddLab3(lab,7)==3))
00277 {
00278 *newp = 0;
00279 }
00280 else
00281 {
00282 *newp = 255;
00283 }
00284 }
00285 }
00286 }
00287 else
00288 {
00289 *newp = 255;
00290 }
00291
00292 }
00293
00294 }
00295 }
00296
00297
00298
00299
00300
00301
00302 void
00303 LabeledSkeletonImage::sequentSkelet()
00304 {
00305 GreyLevelImage::value_type lab[10];
00306 float grad[9];
00307
00308 for (int i = 1 ; i < (_height - 1) ; ++i)
00309 {
00310 GreyLevelImage::value_type* oldp = _pPixMap + (i * _width) + 1;
00311 GreyLevelImage::value_type* newp = _pixMap2 + (i * _width) + 1;
00312
00313 for (int j = 1 ; j < (_width - 1) ; ++j, ++newp, ++oldp)
00314 {
00315 if(*newp == 0)
00316 {
00317
00318 loadLabeledNeighbors(oldp, lab);
00319 gradient(lab, grad);
00320
00321 int indmax = maxGradientPos1(oldp, grad);
00322 int indmax2 = maxGradientPos2(grad, oldp, indmax);
00323
00324 int encore = 1;
00325 while (encore)
00326 {
00327 GreyLevelImage::value_type* savoldp = oldp;
00328 GreyLevelImage::value_type* savnewp = newp;
00329 while (indmax != 0)
00330 {
00331
00332 switch(indmax)
00333 {
00334 case 1:
00335 --oldp;
00336 --newp;
00337 *newp = 1;
00338 break;
00339 case 2:
00340 oldp -= _width + 1;
00341 newp -= _width + 1;
00342 *newp = 1;
00343 break;
00344 case 3:
00345 oldp -= _width;
00346 newp -= _width;
00347 *newp = 1;
00348 break;
00349 case 4:
00350 oldp -= _width - 1;
00351 newp -= _width - 1;
00352 *newp = 1;
00353 break;
00354 case 5:
00355 ++oldp;
00356 ++newp;
00357 *newp = 1;
00358 break;
00359 case 6:
00360 oldp += _width + 1;
00361 newp += _width + 1;
00362 *newp = 1;
00363 break;
00364 case 7:
00365 oldp += _width;
00366 newp += _width;
00367 *newp = 1;
00368 break;
00369 case 8:
00370 oldp += _width - 1;
00371 newp += _width - 1;
00372 *newp = 1;
00373 break;
00374 default:
00375 break;
00376 }
00377
00378
00379 loadLabeledNeighbors(oldp, lab);
00380 gradient(lab, grad);
00381
00382 indmax = maxGradientPos1(oldp, grad);
00383 }
00384
00385
00386 oldp = savoldp;
00387 newp = savnewp;
00388
00389 if (indmax2 != 0)
00390 {
00391 encore = 1;
00392 indmax = indmax2;
00393 indmax2 = 0;
00394 }
00395 else
00396 {
00397 encore = 0;
00398 }
00399 }
00400 }
00401 }
00402
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411 void
00412 LabeledSkeletonImage::finalThinning()
00413 {
00414 GreyLevelImage::value_type lab[10];
00415
00416 for (int i = 1 ; i < (_height - 1) ; ++i)
00417 {
00418 GreyLevelImage::value_type* newp = _pixMap2 + (i * _width) + 1;
00419
00420 for (int j = 1 ; j < (_width - 1) ; ++j, ++newp)
00421 {
00422 if (*newp == 0)
00423 {
00424 loadLabeledNeighbors(newp, lab);
00425 unitWidth(newp, lab);
00426 }
00427 else
00428 {
00429 if ((*(newp - 1) == 0) && (*(newp - _width) == 0) &&
00430 (*(newp + 1) == 0) && (*(newp + _width) == 0))
00431 {
00432
00433 *newp = 0;
00434
00435
00436
00437 GreyLevelImage::value_type* savp = newp;
00438
00439 --newp;
00440 loadLabeledNeighbors(newp, lab);
00441 unitWidth(newp, lab);
00442
00443 newp = savp - _width;
00444 loadLabeledNeighbors(newp, lab);
00445 unitWidth(newp, lab);
00446
00447
00448 newp = savp;
00449 }
00450 }
00451 }
00452 }
00453 }
00454
00455
00456
00457
00458
00459 void
00460 LabeledSkeletonImage::pruning(vector< GenPoint<int> >& myEndPoints,
00461 int maxPruning)
00462 {
00463 GreyLevelImage::value_type n[10];
00464 vector<Point>::iterator myIter = myEndPoints.begin();
00465
00466
00467 vector<GreyLevelImage::value_type*> pointsToBePruned;
00468
00469 while (myIter != myEndPoints.end())
00470 {
00471
00472 Point endP = *myIter;
00473
00474 GreyLevelImage::value_type* startOldP = _pPixMap + (endP.y() * _width) + endP.x();
00475 GreyLevelImage::value_type* startNewP = _pixMap2 + (endP.y() * _width) + endP.x();
00476
00477 GreyLevelImage::value_type* currOldP = startOldP;
00478 GreyLevelImage::value_type* currNewP = startNewP;
00479
00480
00481 int nextPosition = 0;
00482 int d34 = 0;
00483 loadBinaryNeighbors(currNewP, n);
00484
00485 for (int k = 1 ; (k < 9) && (nextPosition == 0) ; ++k)
00486 {
00487 if (n[k] != 0)
00488 {
00489 nextPosition = k;
00490 }
00491 }
00492
00493 int iCameFrom = 0;
00494
00495
00496 switch (nextPosition)
00497 {
00498 case 1:
00499 --currOldP;
00500 --currNewP;
00501 d34 += 3;
00502 iCameFrom = 5;
00503 break;
00504 case 2:
00505 currOldP -= _width + 1;
00506 currNewP -= _width + 1;
00507 d34 += 4;
00508 iCameFrom = 6;
00509 break;
00510 case 3:
00511 currOldP -= _width;
00512 currNewP -= _width;
00513 d34 += 3;
00514 iCameFrom = 7;
00515 break;
00516 case 4:
00517 currOldP -= _width - 1;
00518 currNewP -= _width - 1;
00519 d34 += 4;
00520 iCameFrom = 8;
00521 break;
00522 case 5:
00523 ++currOldP;
00524 ++currNewP;
00525 d34 += 3;
00526 iCameFrom = 1;
00527 break;
00528 case 6:
00529 currOldP += _width + 1;
00530 currNewP += _width + 1;
00531 iCameFrom = 2;
00532 d34 += 4;
00533 break;
00534 case 7:
00535 currOldP += _width;
00536 currNewP += _width;
00537 iCameFrom = 3;
00538 d34 += 3;
00539 break;
00540 case 8:
00541 currOldP += _width - 1;
00542 currNewP += _width - 1;
00543 iCameFrom = 4;
00544 d34 += 4;
00545 break;
00546 default:
00547 break;
00548 }
00549
00550
00551 if (((*currOldP > *startOldP) ||
00552 (((*currOldP + 2)/3) == ((*startOldP +2)/3))) &&
00553 ((*startOldP - *currOldP + d34) <= 3 * maxPruning))
00554 {
00555
00556 vector<GreyLevelImage::value_type*> possiblePointsToBePruned;
00557
00558
00559 possiblePointsToBePruned.push_back(startNewP);
00560
00561
00562 int canContinue = 1;
00563
00564 int canPrune = 1;
00565
00566 while (canContinue)
00567 {
00568
00569 int mydeg = degree(currNewP);
00570 if (mydeg > 2)
00571 canContinue = 0;
00572 else if (mydeg < 2)
00573 {
00574 canContinue = 0;
00575 canPrune = 0;
00576 }
00577 else
00578 {
00579
00580 GreyLevelImage::value_type* savNewP = currNewP;
00581
00582
00583
00584
00585
00586 nextPosition = 0;
00587 loadBinaryNeighbors(currNewP, n);
00588 for (int k = 1 ; (k < 9) && (nextPosition == 0) ; ++k)
00589 {
00590 if ((n[k] != 0) && (k != iCameFrom))
00591 {
00592 nextPosition = k;
00593 }
00594 }
00595
00596
00597 switch (nextPosition)
00598 {
00599 case 1:
00600 --currOldP;
00601 --currNewP;
00602 d34 += 3;
00603 iCameFrom = 5;
00604 break;
00605 case 2:
00606 currOldP -= _width + 1;
00607 currNewP -= _width + 1;
00608 d34 += 4;
00609 iCameFrom = 6;
00610 break;
00611 case 3:
00612 currOldP -= _width;
00613 currNewP -= _width;
00614 d34 += 3;
00615 iCameFrom = 7;
00616 break;
00617 case 4:
00618 currOldP -= _width - 1;
00619 currNewP -= _width - 1;
00620 d34 += 4;
00621 iCameFrom = 8;
00622 break;
00623 case 5:
00624 ++currOldP;
00625 ++currNewP;
00626 d34 += 3;
00627 iCameFrom = 1;
00628 break;
00629 case 6:
00630 currOldP += _width + 1;
00631 currNewP += _width + 1;
00632 iCameFrom = 2;
00633 d34 += 4;
00634 break;
00635 case 7:
00636 currOldP += _width;
00637 currNewP += _width;
00638 iCameFrom = 3;
00639 d34 += 3;
00640 break;
00641 case 8:
00642 currOldP += _width - 1;
00643 currNewP += _width - 1;
00644 iCameFrom = 4;
00645 d34 += 4;
00646 break;
00647 default:
00648 break;
00649 }
00650
00651
00652 if (((*currOldP > *startOldP) ||
00653 (((*currOldP + 2)/3) == ((*startOldP +2)/3))) &&
00654 ((*startOldP - *currOldP + d34) <= 3 * maxPruning))
00655
00656 {
00657 possiblePointsToBePruned.push_back(savNewP);
00658 mydeg = degree(currNewP);
00659 }
00660 else
00661 {
00662 canContinue = 0;
00663 canPrune = 0;
00664 }
00665
00666 }
00667 }
00668
00669 if (canPrune != 0)
00670 {
00671
00672 pointsToBePruned.insert(pointsToBePruned.end(),
00673 possiblePointsToBePruned.begin(),
00674 possiblePointsToBePruned.end());
00675 }
00676
00677 possiblePointsToBePruned.erase(possiblePointsToBePruned.begin(),
00678 possiblePointsToBePruned.end());
00679
00680 }
00681 else
00682 {
00683
00684 }
00685
00686
00687 ++myIter;
00688 }
00689
00690
00691
00692
00693 vector<GreyLevelImage::value_type*>::iterator iterPoints =
00694 pointsToBePruned.begin();
00695
00696 while (iterPoints != pointsToBePruned.end())
00697 {
00698 *(*iterPoints) = 255;
00699 ++iterPoints;
00700 }
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715 void
00716 LabeledSkeletonImage::removeJaggedness()
00717 {
00718 GreyLevelImage::value_type n[10];
00719
00720 for (int i = 1 ; i < (_height-1) ; ++i)
00721 {
00722 GreyLevelImage::value_type* newp = _pixMap2 + (i * _width) + 1;
00723 GreyLevelImage::value_type* oldp = _pPixMap + (i * _width) + 1;
00724
00725 for(int j = 1 ; j < (_width - 1) ; ++j, ++newp, ++oldp)
00726 {
00727 if ((*newp == 0) && (degree(newp) == 2))
00728 {
00729 loadBinaryNeighbors(newp, n);
00730
00731 if ((n[2]==1) && (n[4]==1) && (*(oldp-_width)!=0))
00732 {
00733 *newp = 255;
00734 *(newp-_width) = 0;
00735 }
00736 else if ((n[4]==1) && (n[6]==1) && (*(oldp+1)!=0))
00737 {
00738 *newp = 255;
00739 *(newp+1) = 0;
00740 }
00741 else if ((n[6]==1) && (n[8]==1) && (*(oldp+_width)!=0))
00742 {
00743 *newp = 255;
00744 *(newp+_width) = 0;
00745 }
00746
00747 else if ((n[8]==1) && (n[2]==1) && (*(oldp-1)!=0))
00748 {
00749 *newp = 255;
00750 *(newp-1) = 0;
00751 }
00752 }
00753 }
00754 }
00755 }
00756
00757
00758
00759
00760
00761
00762
00763 void
00764 LabeledSkeletonImage::loadLabeledNeighbors(unsigned char* p, unsigned char* n)
00765 {
00766 *n = *p;
00767 ++n;
00768 *n = *(p - 1);
00769 ++n;
00770 *n = *(p - _width - 1);
00771 ++n;
00772 *n = *(p -_width);
00773 ++n;
00774 *n = *(p -_width + 1);
00775 ++n;
00776 *n = *(p + 1);
00777 ++n;
00778 *n = *(p + _width + 1);
00779 ++n;
00780 *n = *(p + _width);
00781 ++n;
00782 *n = *(p + _width - 1);
00783 ++n;
00784 *n = *(p - 1);
00785 }
00786
00787
00788
00789
00790
00791
00792 void
00793 LabeledSkeletonImage::loadBinaryNeighbors(unsigned char* p, unsigned char* n)
00794 {
00795 *n = *p ? 0 : 1;
00796 ++n;
00797 *n = *(p-1) ? 0 : 1;
00798 ++n;
00799 *n = *(p - _width - 1) ? 0 : 1;
00800 ++n;
00801 *n = *(p - _width) ? 0 : 1;
00802 ++n;
00803 *n = *(p - _width + 1) ? 0 : 1;
00804 ++n;
00805 *n = *(p + 1) ? 0 : 1;
00806 ++n;
00807 *n = *(p + _width + 1) ? 0 : 1;
00808 ++n;
00809 *n = *(p + _width) ? 0 : 1;
00810 ++n;
00811 *n = *(p + _width - 1) ? 0 : 1;
00812 ++n;
00813 *n = *(p - 1) ? 0 : 1;
00814 }
00815
00816
00817
00818
00819
00820
00821 void
00822 LabeledSkeletonImage::loadSuitXBinary(unsigned char suitbin[], unsigned char n[])
00823 {
00824 for (int i = 1 ; i < 10 ; ++i)
00825 {
00826 if ((n[i] < n[0]) && (n[i] != 255))
00827 {
00828 suitbin[i] = 1;
00829 }
00830 else
00831 {
00832 suitbin[i] = 0;
00833 }
00834 }
00835 }
00836
00837
00838
00839
00840
00841
00842 void
00843 LabeledSkeletonImage::loadSuitCBinary(unsigned char suitbin[], unsigned char n[])
00844 {
00845 for (int i = 1 ; i < 10 ; ++i)
00846 {
00847 if((n[i] > n[0]) && (n[i] != 255))
00848 {
00849 suitbin[i] = 1;
00850 }
00851 else
00852 {
00853 suitbin[i] = 0;
00854 }
00855 }
00856 }
00857
00858
00859
00860
00861
00862
00863 int
00864 LabeledSkeletonImage::connexityCnt(unsigned char n[])
00865 {
00866 int c8 = 0;
00867
00868 for (int k = 1 ; k <= 4 ; ++k)
00869 {
00870 int k2 = 2 * k;
00871 int tmp = 1 - n[k2 - 1];
00872 c8 += tmp - (tmp * (1 - n[k2]) * (1 - n[k2 + 1]));
00873 }
00874
00875 return c8;
00876 }
00877
00878
00879
00880
00881
00882
00883 int
00884 LabeledSkeletonImage::crossingCnt(unsigned char n[])
00885 {
00886 int x4 = 0;
00887
00888 for(int k = 1 ; k <= 8 ; ++k)
00889 {
00890 x4 += std::abs(n[k + 1] - n[k]);
00891 }
00892
00893 x4 /= 2;
00894 return x4;
00895 }
00896
00897
00898
00899
00900
00901
00902 int
00903 LabeledSkeletonImage::degree(unsigned char* p)
00904 {
00905 int d = 0;
00906
00907 if(*(p-1) != 255)
00908 {
00909 ++d;
00910 }
00911 if(*(p - _width - 1) != 255)
00912 {
00913 ++d;
00914 }
00915 if(*(p - _width) != 255)
00916 {
00917 ++d;
00918 }
00919 if(*(p - _width + 1) != 255)
00920 {
00921 ++d;
00922 }
00923 if(*(p + 1) != 255)
00924 {
00925 ++d;
00926 }
00927 if(*(p + _width + 1) != 255)
00928 {
00929 ++d;
00930 }
00931 if(*(p + _width) != 255)
00932 {
00933 ++d;
00934 }
00935 if(*(p + _width - 1) != 255)
00936 {
00937 ++d;
00938 }
00939
00940 return d;
00941 }
00942
00943
00944
00945
00946
00947
00948 int
00949 LabeledSkeletonImage::oddEvenOddLab3(unsigned char n[], int debut)
00950 {
00951 return n[debut] + n[debut + 1] + n[debut + 2];
00952 }
00953
00954
00955
00956
00957
00958
00959 void
00960 LabeledSkeletonImage::gradient(unsigned char n[], float grad[])
00961 {
00962 float* g = grad;
00963 *g++ = 0.0;
00964
00965 unsigned char* pn = n + 1;
00966
00967 for (int k = 1 ; k < 9 ; ++k)
00968 {
00969 *g++ = (float) (*pn++ - *n) / (((k % 2) == 0) ? 4.0 : 3.0);
00970 }
00971 }
00972
00973
00974
00975
00976
00977
00978 int
00979 LabeledSkeletonImage::maxGradientPos1(unsigned char* p, float grad[])
00980 {
00981 int ind = 0;
00982 float* g = grad + 1;
00983
00984 for(int k = 1 ; k < 9 ; ++k, ++g)
00985 {
00986 if (*g > grad[0])
00987 {
00988 ind = k;
00989 grad[0] = *g;
00990 }
00991 }
00992
00993 return ind;
00994 }
00995
00996
00997
00998
00999
01000
01001 int
01002 LabeledSkeletonImage::maxGradientPos2(float grad[], unsigned char* p, int indmax)
01003 {
01004 int ind=0;
01005
01006 if ((*p == 3) || (*p == 4))
01007 {
01008 float* g = grad + indmax + 1;
01009
01010 for(int k = indmax + 1 ; k < 9 ; ++k, ++g)
01011 {
01012 if(*g == grad[0])
01013 {
01014 ind = k;
01015 }
01016 }
01017 }
01018
01019 return ind;
01020 }
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033 void
01034 LabeledSkeletonImage::unitWidth(unsigned char* p, unsigned char lab[])
01035 {
01036 if (((lab[1] == 255) || (lab[3] == 255) ||
01037 (lab[5] == 255) || (lab[7] == 255))
01038 &&
01039 (((lab[1] == 0) && (lab[3] == 0) && (lab[6] == 255)) ||
01040 ((lab[3] == 0) && (lab[5] == 0) && (lab[8] == 255)) ||
01041 ((lab[5] == 0) && (lab[7] == 0) && (lab[2] == 255)) ||
01042 ((lab[7] == 0) && (lab[1] == 0) && (lab[4] == 255))))
01043 {
01044 *p = 255;
01045 }
01046 }
01047
01048
01049
01050
01051 }