public static Contour TraceContour(int a_iStartingPixelIndex, NeighborDirection a_eStartingDirection, int a_iContourLabel, BinarizedImage a_rBinarizedImage, int[] a_rLabelMap) { int iPixelIndexTrace; NeighborDirection eDirectionNext = a_eStartingDirection; FindNextPoint(a_iStartingPixelIndex, a_eStartingDirection, a_rBinarizedImage, a_rLabelMap, out iPixelIndexTrace, out eDirectionNext); Contour oContour = new Contour(a_iContourLabel); oContour.AddFirst(a_rBinarizedImage.PixelIndex2Coords(iPixelIndexTrace)); int iPreviousPixelIndex = a_iStartingPixelIndex; int iCurrentPixelIndex = iPixelIndexTrace; bool bDone = (a_iStartingPixelIndex == iPixelIndexTrace); // Choose a bias factor // The bias factor points to exterior if tracing an outer contour // The bias factor points to interior if tracing an inner contour float fOrthoBiasFactor; if (a_eStartingDirection == NeighborDirection.DirectionUpRight) // inner contour { fOrthoBiasFactor = -0.2f; } else // outer contour { fOrthoBiasFactor = 0.2f; } while (bDone == false) { a_rLabelMap[iCurrentPixelIndex] = a_iContourLabel; NeighborDirection eDirectionSearch = (NeighborDirection)(((int)eDirectionNext + 6) % 8); int iNextPixelIndex; FindNextPoint(iCurrentPixelIndex, eDirectionSearch, a_rBinarizedImage, a_rLabelMap, out iNextPixelIndex, out eDirectionNext); iPreviousPixelIndex = iCurrentPixelIndex; iCurrentPixelIndex = iNextPixelIndex; bDone = (iPreviousPixelIndex == a_iStartingPixelIndex && iCurrentPixelIndex == iPixelIndexTrace); if (bDone == false) { // Apply some bias to inner and outer contours to avoid them overlap // Use the orthogonal vector to direction NeighborDirection eOrthoBiasDirection = (NeighborDirection)(((int)eDirectionNext + 6) % 8); // == direction - 2 % 8 but easier to compute (always positive) Vector2 f2Bias = fOrthoBiasFactor * BinarizedImage.GetDirectionVector(eOrthoBiasDirection); // Add bias to pixel pos Vector2 f2BiasedPos = f2Bias + a_rBinarizedImage.PixelIndex2Coords(iNextPixelIndex); // Add biased pos to contour oContour.AddFirst(f2BiasedPos); } } return(oContour); }