I watched part of a course video of “Introduction to Image Segmentation” by Yuri Boykov (University of Western Ontario) this afternoon, and at the beginning of this course, he mentioned an algorithm about active contour, which also called snakes, is a framework for delineating an object outline from a possibly noisy 2D image. By searching on google, I found that in OpenCV, there is a function “cvSnakeImage” which is exactly using this alrorithm, so I read the OpenCV Snake code, andtried this algorithm with a picture.

The active contour model introduces several energy terms, and when the sum of internal and external energy is minimal, we got the contour we want, so what the algorithm do is actually updates the snake in order to minimize its total energy, that is a sum of internal energy that depends on the contour shape (the smoother contour is, the smaller internal energy is) and external energy.

In OpenCV code, the cvSnakeImage() is something like:

while( !converged ){ for( i = 0; i < number_of_points; i++ ){ Calculate Econt Calculate Ecurv Calculate Eimg ENERGY = alpha * Econt + beta * Ecurv + gamma * Eimg; } }

For testing this algorithm, I used this picture.

I used Otsu’s method to get a binary image.

As we seen, otsu’s method just made some part of the shadow black, ignore it, we are not discussing thresholding method ðŸ™‚

In addition, **there are some pixels white on the binary image**, because there is light on the original image, near the contour, we will fix this later.

I used 100 points as original points of contour (blue points in picture), and by updating, the snake function returns a better contour.

- Blue: original points
- Green: points after 20 loops
- Yellow: points after 50 loops
- Cyan: points after 70 loops
- Purple: points after 100 loops
- Red: points after 1000 loops

Better contour but not good enough, there are obviously some place that not belongs to the lens in the red contour, maybe given more time, this function can do better, but I think maybe I can use the result of cv::findContours as my input points, and let’s find out if it can work!

Really better, but at the same time, problem appears, the contour we found is inside the lens in some places, that is exactly because the light on original image, and I’m going to fix it by Erode the binary image.

IplConvKernel* pb=cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_RECT,NULL); cvErode(bin,erode,pb,2); cvReleaseStructuringElement(&pb); Mat Binmat(erode, 0); findContours(Binmat, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE); cvSnakeImage( bin, contours, length_of_contours, &alpha, &beta, &gamma, CV_VALUE, cvSize(3,3), criteria, 2 );

And now what’s the result?

The blue line is contour found after erode, and red points are contour updated by snake function.

Awesome!

p.s. This is an interesting paper about Snake ðŸ™‚

Pingback: Background Substraction – Hedonism()