00001
00010 #include "tuw_utils/contour.h"
00011 #include <iostream>
00012 #include <stack>
00013 #include <cstdio>
00014 #include "opencv/highgui.h"
00015
00016 namespace tuw {
00017
00018 const int Contour::ANGLE_8U = 8;
00019 const int Contour::ANGLE_32F = 32;
00020 const int Contour::ANGLE_64F = 64;
00021
00022
00023 const int Contour::MODE_SIMPLE = 1;
00024 const int Contour::MODE_CONTOUR = 2;
00025 const int Contour::MODE_GRAIDENT = 3;
00026 const int Contour::MODE_COMPLEX = 4;
00027
00028 const float Contour::fPi = 3.1415926535897932384626433832795;
00029 const double Contour::dPi = 3.1415926535897932384626433832795;
00030
00031 const int Contour::pppDirectionWeightsField[4][3][3] = {
00032 { {2,1,2},
00033 {4,0,4},
00034 {2,1,2}
00035 },
00036 { {1,2,4},
00037 {2,0,2},
00038 {4,2,1}
00039 },
00040 { {2,4,2},
00041 {1,0,1},
00042 {2,4,4}
00043 },
00044 { {4,2,1},
00045 {2,0,2},
00046 {1,2,4}
00047 }
00048 };
00049
00050 const int Contour::ppGradientWeightsField[4][9] = {
00051 {3, 5, 6, 8, 2, 0, 7, 1, 4},
00052 {2, 6, 1, 3, 7, 5, 0, 8, 4},
00053 {1, 7, 0, 6, 8, 2, 3, 5, 4},
00054 {0, 8, 1, 7, 5, 3, 2, 6, 4}
00055 };
00056
00057 const int Contour::pppCommingFromEdgeWeightsField[9][3][3] = {
00058 { {0,1,2},
00059 {1,0,3},
00060 {2,3,4}
00061 },
00062 { {1,0,1},
00063 {2,0,2},
00064 {3,4,3}
00065 },
00066 { {2,1,0},
00067 {3,0,1},
00068 {4,3,2}
00069 },
00070 { {1,2,3},
00071 {0,0,4},
00072 {1,2,3}
00073 },
00074 { {0,0,0},
00075 {0,0,0},
00076 {0,0,0}
00077 },
00078 { {3,2,1},
00079 {4,0,0},
00080 {3,2,1}
00081 },
00082 { {2,3,4},
00083 {1,0,3},
00084 {0,1,2}
00085 },
00086 { {3,4,3},
00087 {2,0,2},
00088 {1,0,1}
00089 },
00090 { {4,3,2},
00091 {3,0,1},
00092 {2,1,0}
00093 }
00094 };
00095
00096 const int Contour::ppContourWeightsField[9][9] = {
00097 {8, 7, 5, 6, 2, 3, 1, 0, 4},
00098 {7, 6, 8, 3, 5, 0, 2, 1, 4},
00099 {6, 7, 3, 8, 0, 5, 1, 2, 4},
00100 {5, 2, 8, 1, 7, 0, 6, 3, 4},
00101 {0, 0, 0, 0, 0, 0, 0, 0, 0},
00102 {3, 6, 0, 7, 1, 8, 2, 5, 4},
00103 {2, 1, 5, 0, 8, 3, 7, 6, 4},
00104 {1, 2, 0, 3, 5, 6, 8, 7, 4},
00105 {0, 1, 3, 2, 6, 5, 7, 8, 4}
00106 };
00107
00108 Contour::Contour() :
00109 mpImgEdge ( NULL ),
00110 mpImgEdgeDirection ( NULL ),
00111 mdImgEdgeDirectionType ( 0 ),
00112 mdefEdgeLinkMode ( 0 ),
00113 mImgWidth ( 0 ),
00114 mImgHeight ( 0 ),
00115 mbAllowToModifyTheSources ( false ),
00116
00117 mNrOfEdges ( 0 ) {}
00118
00119 Contour::~Contour() {
00120 Contour::RelaseMemory();
00121 }
00122
00123 void Contour::AllocateMemory() {
00124 RelaseMemory();
00125 if ( mbAllowToModifyTheSources == false ) {
00126 mpImgEdge = ( unsigned char* ) malloc ( sizeof ( unsigned char ) * mImgWidth * mImgHeight );
00127 }
00128
00129 mEdges.resize ( mImgWidth * mImgHeight );
00130 mAngle8Bit.resize ( mImgWidth * mImgHeight );
00131 }
00132
00133 void Contour::RelaseMemory() {
00134 if ( mbAllowToModifyTheSources ) {
00135 if ( mpImgEdge != NULL ) {
00136 free ( mpImgEdge );
00137 mpImgEdge = NULL;
00138 }
00139
00140
00141
00142
00143
00144
00145 }
00146 }
00147
00148 int Contour::getContours( std::vector<std::vector<cv::Point> > &contours, unsigned int min_length) {
00149 contours.clear();
00150 std::vector<cv::Range> idx = getSegmentIndexes () ;
00151 for ( unsigned int i = 0; i < idx.size(); i++ ) {
00152 int length = idx[i].end - idx[i].start;
00153 if (length > min_length) {
00154 contours.push_back(std::vector<cv::Point>());
00155 for ( int index = idx[i].start; index < idx[i].end; index++ ) {
00156 CvPoint &edge = (mEdges)[index];
00157 contours.back().push_back( edge);
00158 }
00159 }
00160 }
00161 return contours.size();
00162 }
00163
00164 void Contour::Draw( unsigned char* pImgRGB ) {
00165 unsigned char *pDes;
00166 std::vector<cv::Range> idx = getSegmentIndexes () ;
00167 for ( unsigned int i = 0; i < idx.size(); i++ ) {
00168 unsigned char pColor[] = {rand() / ( RAND_MAX/0xFF ), rand() / ( RAND_MAX/0xFF ), rand() / ( RAND_MAX/0xFF ) };
00169 for ( int index = idx[i].start; index < idx[i].end; index++ ) {
00170 CvPoint edge = (mEdges)[index];
00171 pDes = pImgRGB + ( 3 * ( mImgWidth * edge.y + edge.x ) );
00172 for ( int j = 0; j < 3; j++ ) {
00173 pDes[j] = pColor[j];
00174 }
00175 }
00176 }
00177 }
00178
00179 void Contour::Init ( unsigned int iImgWidth, unsigned int iImgHeight, bool bAllowToModifyTheSources, unsigned char iEdgeToProcess, unsigned char iEdgeInProcess, unsigned char iEdgeProcessed, unsigned char iEdgeStrengthRemoved ) {
00180 if((iImgWidth != mImgWidth) || (mImgHeight != iImgHeight) ||
00181 (mbAllowToModifyTheSources != bAllowToModifyTheSources) || (mEdgeToProcess != iEdgeToProcess) ||
00182 (mEdgeInProcess != iEdgeInProcess) || (mEdgeProcessed != iEdgeProcessed)) {
00183 RelaseMemory();
00184 mImgWidth = iImgWidth;
00185 mImgHeight = iImgHeight;
00186 mbAllowToModifyTheSources = bAllowToModifyTheSources;
00187 mEdgeToProcess = iEdgeToProcess;
00188 mEdgeInProcess = iEdgeInProcess;
00189 mEdgeProcessed = iEdgeProcessed;
00190 AllocateMemory();
00191 }
00192 }
00193
00194 int Contour::GetImgDirectionIndex ( CvPoint tPoint ) {
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 int iIndex = 0;
00205 unsigned char i8BitAngle;
00206 float fAngle;
00207 double dAngle;
00208 switch ( mdImgEdgeDirectionType ) {
00209 case ANGLE_8U:
00210 i8BitAngle = ( ( unsigned char* ) mpImgEdgeDirection ) [tPoint.y*mImgWidth + tPoint.x];
00211 if ( i8BitAngle > 128 ) {
00212 i8BitAngle -= 128;
00213 }
00214 i8BitAngle = i8BitAngle + 16;
00215 iIndex = i8BitAngle / 32;
00216 break;
00217 case ANGLE_32F:
00218 fAngle = ( ( float* ) mpImgEdgeDirection ) [tPoint.y*mImgWidth + tPoint.x];
00219 if ( fAngle < 0 ) {
00220 fAngle += fPi;
00221 }
00222 iIndex = ( int ) ( ( fAngle + fPi/8 ) * 3/fPi );
00223 break;
00224 case ANGLE_64F:
00225 dAngle = ( ( double* ) mpImgEdgeDirection ) [tPoint.y*mImgWidth + tPoint.x];
00226
00227 if ( dAngle < 0 ) {
00228 dAngle += dPi;
00229 }
00230 iIndex = ( int ) ( ( dAngle + dPi/8 ) * 3/dPi );
00231 break;
00232 }
00233 return iIndex;
00234 }
00235
00236 void Contour::Perform ( unsigned char* pImgEdgeStrength, int defEdgeLinkMode, void* pImgEdgeDirection, int dImgEdgeDirectionType ) {
00237 mNrOfEdges = 0;
00238 mSegments.clear();
00239 mSegments.reserve ( 100 );
00240 mdefEdgeLinkMode = defEdgeLinkMode;
00241 mpImgEdgeDirection = pImgEdgeDirection;
00242 mdImgEdgeDirectionType = dImgEdgeDirectionType;
00243 if ( mbAllowToModifyTheSources ) {
00244 mpImgEdge = pImgEdgeStrength;
00245 } else {
00246 memcpy ( mpImgEdge, pImgEdgeStrength, mImgWidth * mImgHeight );
00247 }
00248
00249 switch ( mdefEdgeLinkMode ) {
00250 case MODE_SIMPLE:
00251 Linking_Simple();
00252 break;
00253 case MODE_CONTOUR:
00254 Linking_Contour();
00255 break;
00256 case MODE_GRAIDENT:
00257 if ( pImgEdgeDirection == NULL ) {
00258 printf ( "The linker mode requires an edge direction image!\n" );
00259 }
00260 Linking_Gradient();
00261 break;
00262 case MODE_COMPLEX:
00263 if ( pImgEdgeDirection == NULL ) {
00264 printf ( "The linker mode requires an edge direction image!\n" );
00265 }
00266 Linking_Complex();
00267 break;
00268 }
00269 }
00270
00271
00272 void Contour::Linking_Simple() {
00273 CvPoint tPoint = {0,0};
00274 cv::Range range(0,0);
00275 for ( tPoint.y = 1; tPoint.y < mImgHeight-1; tPoint.y++ ) {
00276 tPoint.x = 1;
00277 unsigned char *pCurrent = getImgEdge ( tPoint );
00278 for ( ; tPoint.x < mImgWidth-1; tPoint.x++ ) {
00279 if ( *pCurrent >= mEdgeToProcess ) {
00280 range.start = mNrOfEdges;
00281 Trace_Simple ( tPoint, &range.end );
00282 mSegments.push_back ( range );
00283
00284 }
00285 pCurrent++;
00286 }
00287 }
00288 }
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 void Contour::Trace_Simple ( CvPoint tPoint, int *pEnd ) {
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 if (isInImage(tPoint)) {
00336 unsigned char *pPix = getImgEdge ( tPoint );
00337 CvPoint tCurrent = tPoint;
00338 bool bEnd = false;
00339 bool bStart = false;
00340 std::stack<CvPoint> trace_to_start;
00341 std::stack<CvPoint> trace_to_end;
00342 std::stack<CvPoint> *pEdgeStack = &trace_to_start;
00343 while (bEnd == false) {
00344
00345
00346
00347
00348
00349
00350 *pPix = mEdgeProcessed;
00351 pEdgeStack->push(tCurrent);
00352 if (pPix[-mImgWidth-1] >= mEdgeToProcess) {
00353 pPix = pPix-mImgWidth-1;
00354 tCurrent.x--, tCurrent.y--;
00355 } else if (pPix[-mImgWidth] >= mEdgeToProcess) {
00356 pPix = pPix-mImgWidth;
00357 tCurrent.y--;
00358 } else if ( pPix[-mImgWidth+1] >= mEdgeToProcess) {
00359 pPix = pPix-mImgWidth+1;
00360 tCurrent.x++, tCurrent.y--;
00361 } else if (pPix[-1] >= mEdgeToProcess) {
00362 pPix = pPix-1;
00363 tCurrent.x--;
00364 } else if (pPix[+1] >= mEdgeToProcess) {
00365 pPix = pPix+1;
00366 tCurrent.x++;
00367 } else if (pPix[mImgWidth-1] >= mEdgeToProcess) {
00368 pPix = pPix + mImgWidth-1;
00369 tCurrent.x--, tCurrent.y++;
00370 } else if (pPix[mImgWidth] >= mEdgeToProcess) {
00371 pPix = pPix + mImgWidth;
00372 tCurrent.y++;
00373 } else if (pPix[mImgWidth+1] >= mEdgeToProcess) {
00374 pPix = pPix + mImgWidth + 1;
00375 tCurrent.x++, tCurrent.y++;
00376 } else {
00377 if (bStart == false) {
00378 bStart = true;
00379 while (!trace_to_start.empty()) {
00380 trace_to_end.push(trace_to_start.top());
00381 trace_to_start.pop();
00382 }
00383 pEdgeStack = &trace_to_end;
00384 tCurrent = pEdgeStack->top();
00385 pEdgeStack->pop();
00386 pPix = getImgEdge ( tCurrent );
00387 } else {
00388 bEnd = true;
00389 }
00390 }
00391 }
00392 while (!pEdgeStack->empty()) {
00393 CvPoint p = pEdgeStack->top();
00394 mEdges[mNrOfEdges++] = p;
00395 pEdgeStack->pop();
00396 }
00397
00398 *pEnd = (mNrOfEdges-1);
00399 }
00400 }
00401
00402 void Contour::Linking_Contour() {
00403 CvPoint tPoint = {0,0};
00404 cv::Range range(0,0);
00405 for ( tPoint.y = 1; tPoint.y < ( int ) mImgHeight-1; tPoint.y++ ) {
00406 tPoint.x = 1;
00407 unsigned char *pCurrent = getImgEdge ( tPoint );
00408 for ( ; tPoint.x < ( int ) mImgWidth-1; tPoint.x++ ) {
00409 if ( *pCurrent >= mEdgeToProcess ) {
00410 range.start = mNrOfEdges;
00411 Trace_Contour ( tPoint, &range.end, 0 );
00412 mSegments.push_back ( range );
00413
00414 }
00415 pCurrent++;
00416 }
00417 }
00418 }
00419
00420 void Contour::Trace_Contour ( CvPoint tPoint, int *pEnd, unsigned int iCommingFromEdge ) {
00421
00422
00423
00424
00425
00426
00427
00428
00429 if (isInImage(tPoint)) {
00430 unsigned char *pPix = getImgEdge ( tPoint );
00431 CvPoint tCurrent = tPoint;
00432 bool bEnd = false;
00433 bool bStart = false;
00434 std::stack<CvPoint> trace_to_start;
00435 std::stack<CvPoint> trace_to_end;
00436 std::stack<CvPoint> *pEdgeStack = &trace_to_start;
00437 while (bEnd == false) {
00438 *pPix = mEdgeProcessed;
00439 pEdgeStack->push(tCurrent);
00440 if (pPix[-mImgWidth-1] >= mEdgeToProcess) {
00441 pPix = pPix-mImgWidth-1;
00442 tCurrent.x--, tCurrent.y--;
00443 } else if (pPix[-mImgWidth] >= mEdgeToProcess) {
00444 pPix = pPix-mImgWidth;
00445 tCurrent.y--;
00446 } else if ( pPix[-mImgWidth+1] >= mEdgeToProcess) {
00447 pPix = pPix-mImgWidth+1;
00448 tCurrent.x++, tCurrent.y--;
00449 } else if (pPix[-1] >= mEdgeToProcess) {
00450 pPix = pPix-1;
00451 tCurrent.x--;
00452 } else if (pPix[+1] >= mEdgeToProcess) {
00453 pPix = pPix+1;
00454 tCurrent.x++;
00455 } else if (pPix[mImgWidth-1] >= mEdgeToProcess) {
00456 pPix = pPix + mImgWidth-1;
00457 tCurrent.x--, tCurrent.y++;
00458 } else if (pPix[mImgWidth] >= mEdgeToProcess) {
00459 pPix = pPix + mImgWidth;
00460 tCurrent.y++;
00461 } else if (pPix[mImgWidth+1] >= mEdgeToProcess) {
00462 pPix = pPix + mImgWidth + 1;
00463 tCurrent.x++, tCurrent.y++;
00464 } else {
00465 if (bStart == false) {
00466 bStart = true;
00467 while (!trace_to_start.empty()) {
00468 trace_to_end.push(trace_to_start.top());
00469 trace_to_start.pop();
00470 }
00471 pEdgeStack = &trace_to_end;
00472 tCurrent = pEdgeStack->top();
00473 pPix = getImgEdge ( tCurrent );
00474 } else {
00475 bEnd = true;
00476 }
00477 }
00478 }
00479 while (!pEdgeStack->empty()) {
00480 mEdges[mNrOfEdges++] = pEdgeStack->top();
00481 pEdgeStack->pop();
00482 }
00483 *pEnd = mNrOfEdges;
00484 }
00485 }
00486
00487
00488 void Contour::Linking_Gradient() {
00489 CvPoint tPoint = {0,0};
00490 cv::Range range(0,0);
00491 for ( tPoint.y = 1; tPoint.y < ( int ) mImgHeight-1; tPoint.y++ ) {
00492 tPoint.x = 1;
00493 unsigned char *pCurrent = getImgEdge ( tPoint );
00494 for ( ; tPoint.x < ( int ) mImgWidth-1; tPoint.x++ ) {
00495 if ( *pCurrent >= mEdgeToProcess ) {
00496 range.start = mNrOfEdges;
00497 Trace_Gradient ( tPoint, &range.end );
00498 mSegments.push_back ( range );
00499
00500 }
00501 pCurrent++;
00502 }
00503 }
00504 }
00505
00506 void Contour::Trace_Gradient ( CvPoint tPoint, int *pEnd ) {
00507 if (isInImage(tPoint)) {
00508 CvPoint tCurrent = {0,0};
00509 CvPoint tNext = {0,0};
00510 bool bRemove = false;
00511 unsigned char *pNeighbor;
00512 int iEdgeDirection;
00513 if ( mdImgEdgeDirectionType == ANGLE_8U) {
00514 mAngle8Bit[mNrOfEdges] = ( ( unsigned char* ) mpImgEdgeDirection ) [tPoint.y*mImgWidth + tPoint.x];
00515 }
00516 iEdgeDirection = GetImgDirectionIndex ( tPoint );
00517 int *pIndex = ( int* ) ppGradientWeightsField[iEdgeDirection];
00518 for ( int i = 0; i < 9; i++ ) {
00519 tCurrent = GetNeighborPoint ( tPoint, pIndex[i] );
00520 pNeighbor = getImgEdge ( tCurrent );
00521 if ( *pNeighbor >= mEdgeToProcess ) {
00522 if ( pIndex[i] == 4 ) {
00523
00524 *pNeighbor = mEdgeProcessed;
00525 mEdges[mNrOfEdges] = tPoint;
00526 *pEnd = mNrOfEdges;
00527 mNrOfEdges++;
00528 } else {
00529 if ( bRemove ) {
00530 *pNeighbor = mEdgeProcessed;
00531 } else {
00532 bRemove = true;
00533 tNext = tCurrent;
00534 }
00535 }
00536 }
00537 }
00538 if ( bRemove ) {
00539 Trace_Gradient ( tNext, pEnd );
00540 }
00541 }
00542 }
00543
00544
00545 void Contour::Linking_Complex() {
00546 CvPoint tPoint = {0,0};
00547 cv::Range range(0,0);
00548 for ( tPoint.y = 1; tPoint.y < ( int ) mImgHeight-1; tPoint.y++ ) {
00549 tPoint.x = 1;
00550 unsigned char *pCurrent = getImgEdge ( tPoint );
00551 for ( ; tPoint.x < ( int ) mImgWidth-1; tPoint.x++ ) {
00552 if ( *pCurrent >= mEdgeToProcess ) {
00553 range.start = mNrOfEdges;
00554 Trace_Complex ( tPoint, &range.end, 0 );
00555 mSegments.push_back ( range );
00556
00557 }
00558 pCurrent++;
00559 }
00560 }
00561 }
00562
00563 void Contour::Trace_Complex ( CvPoint tPoint, int *pEnd, unsigned int iCommingFromEdge ) {
00564 if (isInImage(tPoint)) {
00565 CvPoint tCurrent;
00566 CvPoint tNext = {0,0};;
00567 bool bRemove = false;
00568 unsigned char *pNeighbor = NULL;
00569 unsigned int iGointToEdge = 0;
00570 int pSum[9];
00571 int pIndex[9];
00572 int iEdgeDirection;
00573 if ( mdImgEdgeDirectionType == ANGLE_8U) {
00574 mAngle8Bit[mNrOfEdges] = ( ( unsigned char* ) mpImgEdgeDirection ) [tPoint.y*mImgWidth + tPoint.x];
00575 }
00576 iEdgeDirection = GetImgDirectionIndex ( tPoint );
00577 SumArrayMatrix ( ( int * ) pppDirectionWeightsField[iEdgeDirection],
00578 ( int * ) pppCommingFromEdgeWeightsField[iCommingFromEdge],
00579 ( int * ) pSum, 9 );
00580 SortArrayIndexes ( pSum, pIndex, 9 );
00581 for ( int i = 0; i < 9; i++ ) {
00582 tCurrent = GetNeighborPoint ( tPoint, pIndex[i] );
00583 pNeighbor = getImgEdge ( tCurrent );
00584 if ( *pNeighbor >= mEdgeToProcess ) {
00585 if ( pIndex[i] == 4 ) {
00586
00587 *pNeighbor = mEdgeProcessed;
00588 mEdges[mNrOfEdges] = tPoint;
00589 *pEnd = mNrOfEdges;
00590 mNrOfEdges++;
00591 } else {
00592 if ( bRemove ) {
00593 *pNeighbor = mEdgeProcessed;
00594 } else {
00595 bRemove = true;
00596 tNext = tCurrent;
00597 iGointToEdge = 8-pIndex[i];
00598 }
00599 }
00600 }
00601 }
00602 if ( bRemove ) {
00603 Trace_Complex ( tNext, pEnd, iGointToEdge );
00604 }
00605 }
00606 }
00607
00608 const CvPoint Contour::GetNeighborPoint ( CvPoint tPoint, int iNeighborIndex ) {
00609 switch ( iNeighborIndex ) {
00610 case 0:
00611 tPoint.x += -1;
00612 tPoint.y += -1;
00613 break;
00614 case 1:
00615 tPoint.x += 0;
00616 tPoint.y += -1;
00617 break;
00618 case 2:
00619 tPoint.x += +1;
00620 tPoint.y += -1;
00621 break;
00622 case 3:
00623 tPoint.x += -1;
00624 tPoint.y += 0;
00625 break;
00626 case 4:
00627 tPoint.x += 0;
00628 tPoint.y += 0;
00629 break;
00630 case 5:
00631 tPoint.x += +1;
00632 tPoint.y += 0;
00633 break;
00634 case 6:
00635 tPoint.x += -1;
00636 tPoint.y += +1;
00637 break;
00638 case 7:
00639 tPoint.x += 0;
00640 tPoint.y += +1;
00641 break;
00642 case 8:
00643 tPoint.x += +1;
00644 tPoint.y += +1;
00645 break;
00646 }
00647 return tPoint;
00648 }
00649 int Contour::GetEdgeListSplittedXY (std::vector<cv::Point_<int> > &rEdges, std::vector<unsigned char> **ppAngle8Bit) {
00650
00651 rEdges.resize ( mEdges.size() );
00652 for (unsigned int i = 0; i < mEdges.size(); i++) {
00653 rEdges[i] = mEdges[i];
00654 }
00655 if (ppAngle8Bit != NULL) {
00656 *ppAngle8Bit = &mAngle8Bit;
00657 }
00658 return mEdges.size();
00659 }
00660
00661 const void Contour::SortArrayIndexes ( int *pArray, int *pIndexes, const int iSize ) {
00662 int iMax = -1;
00663 int iMin = iMax;
00664 int iMaxIndex = 0;
00665 for ( int j = 0; j < iSize; j++ ) {
00666 for ( int i = 0; i < iSize; i++ ) {
00667 if ( pArray[i] > iMax ) {
00668 iMax = pArray[i];
00669 iMaxIndex = i;
00670 }
00671 if ( pArray[i] < iMin ) {
00672 iMin = pArray[i];
00673 }
00674 }
00675 pIndexes[j] = iMaxIndex;
00676 pArray[iMaxIndex] = iMin;
00677 iMax = iMin;
00678 }
00679 }
00680
00681 void Contour::GetAbnormitiesInEdgesImage ( IplImage *ptImgEdge, std::vector<CvPoint> *pAbnormities, uchar iEdgeStrength ) {
00682 pAbnormities->clear();
00683 bool bAbnormities;
00684 CvPoint tPoint;
00685 for ( tPoint.y = 1; tPoint.y < ptImgEdge->height-1; tPoint.y++ ) {
00686 unsigned char *pRow0 = ( unsigned char * ) ptImgEdge->imageData + ptImgEdge->width* ( tPoint.y-1 );
00687 unsigned char *pRow1 = pRow0 + ptImgEdge->width;
00688 unsigned char *pRow2 = pRow1 + ptImgEdge->width;
00689 for ( tPoint.x = 1; tPoint.x < ptImgEdge->width-1; tPoint.x++ ) {
00690 bAbnormities = false;
00691 if ( pRow1[1] > iEdgeStrength ) {
00692 int iNoOfNeighbors = 0;
00693 if ( pRow0[0] > iEdgeStrength ) {
00694 iNoOfNeighbors++;
00695 if ( ( pRow0[1] > iEdgeStrength ) || ( pRow1[0] > iEdgeStrength ) ) {
00696 bAbnormities = true;
00697 }
00698 }
00699 if ( pRow0[1] > iEdgeStrength ) {
00700 iNoOfNeighbors++;
00701 if ( ( pRow0[0] > iEdgeStrength ) || ( pRow0[2] > iEdgeStrength ) ) {
00702 bAbnormities = true;
00703 }
00704 }
00705 if ( pRow0[2] > iEdgeStrength ) {
00706 iNoOfNeighbors++;
00707 if ( ( pRow0[1] > iEdgeStrength ) || ( pRow1[2] > iEdgeStrength ) ) {
00708 bAbnormities = true;
00709 }
00710 }
00711 if ( pRow1[0] > iEdgeStrength ) {
00712 iNoOfNeighbors++;
00713 if ( ( pRow0[0] > iEdgeStrength ) || ( pRow2[0] > iEdgeStrength ) ) {
00714 bAbnormities = true;
00715 }
00716 }
00717 if ( pRow1[2] > iEdgeStrength ) {
00718 iNoOfNeighbors++;
00719 if ( ( pRow0[2] > iEdgeStrength ) || ( pRow2[2] > iEdgeStrength ) ) {
00720 bAbnormities = true;
00721 }
00722 }
00723 if ( pRow2[0] > iEdgeStrength ) {
00724 iNoOfNeighbors++;
00725 if ( ( pRow1[0] > iEdgeStrength ) || ( pRow2[1] > iEdgeStrength ) ) {
00726 bAbnormities = true;
00727 }
00728 }
00729 if ( pRow2[1] > iEdgeStrength ) {
00730 iNoOfNeighbors++;
00731 if ( ( pRow2[0] > iEdgeStrength ) || ( pRow2[2] > iEdgeStrength ) ) {
00732 bAbnormities = true;
00733 }
00734 }
00735 if ( pRow2[2] > iEdgeStrength ) {
00736 iNoOfNeighbors++;
00737 if ( ( pRow2[1] > iEdgeStrength ) || ( pRow1[2] > iEdgeStrength ) ) {
00738 bAbnormities = true;
00739 }
00740 }
00741 if ( bAbnormities ) {
00742 pAbnormities->push_back ( tPoint );
00743 }
00744 }
00745 pRow0++;
00746 pRow1++;
00747 pRow2++;
00748 }
00749 }
00750
00751 }
00752
00753 std::vector<cv::Range> Contour::getSegmentIndexes() {
00754 return mSegments;
00755 }
00756
00757 }