UPDATE:
My new post: Sparse Field Active Contours
implements quicker, more accurate active contours.

The well-known Chan-Vese segmentation algorithm from the paper “Active Contours Without Edges,” is a great example of active contours. This technique deforms an initial curve so that it separates foreground from background based on the means of the two regions. The technique is very robust to initialization and gives very nice results when there is a difference between the foreground and background means.

In this video, the curve begins as a square. As time goes on the square changes shape so that it does a better and better job of separating the image into a light area and a dark area.

Below is a download-able Matlab demo. The code is very easy to read, and could be the foundation for lots of other active contour segmentation techniques.

sfm_chanvese_demo.zip (New! Described Here)
regionbased_seg.zip (old and slow)

I recently added some new active contour stuff based on a more complex (and sometimes more capable energy). Check out the latest results, and the full project writeup which is a little older!

## 27 thoughts on “Active Contours”

1. Tran says:

Very good.Have you done in 3D?

2. April K says:

Hello,
I am using your active contours without edges (regionbased_seg) code and i really like it – thank you for your contribution. I have a few questions/comments.
—–
1) your dphidt only normalizes the F associated with exterior/interior means (i.e. F_ext and F_int). However, shouldn’t the total force (which includes the curvature term) be normalized. For example, you have:
>>dphidt = F./max(abs(F)) + alpha*curvature;
but shouldn’t it be:
>>dphidt = F + alpha*curvature;
>>dphidt = dphidt./(max(abs(dphidt)));

2) when you find the dphidt:
>>dphidt = F./max(abs(F)) + alpha*curvature;
the F term is added. According to Chan/Vese’s Transaction on IP paper, eq.9, should the F1 term (interior force) be subtracted and the F2 term (ext force) be added? Therefore, shouldn’t the update equation be:
>>dphidt = (- F) + alpha*curvature;

I have checked this a few times. Please let me know what you think.
thanks,
April K

3. bzf says:

I have the same question with April K. Also, I wonder the curvature equation in your code that why mutiply *(phi_x2 + phi_y2).^(1/2) in the end of the equation.

I have tried to remove (phi_x2 + phi_y2).^(1/2)from the equation and it works well.

thanks,
bzf

4. bzf says:

er… it seems that my english is not adequated to express my question clearly.

5. April K says:

Hello BZF,

I have noticed that some implementations include the (phi_x2 + phi_y2).^(1/2) term. after i made the modifications above (in my original comments #1) #2)), i tried removing the (phi_x2 + phi_y2).^(1/2) from the curvature term, and it didn’t make a big difference.

Do you agree with my original questions?

6. Alex says:

Hi!

I found the algorithm very useful. However, I have a question about its usability:
Is it possible that the algorithm is used in order to segment regions which are non foreground/background? What I mean is to set manually the initialization mask at a certain part and not let the algorithm set it automatically.

Thanks.

7. Shawn Lankton says:

AprilK tracked me down on IM and got some answers out of me. Here’s the jist:

1) You caught me! That’s a hack : ) It makes the alpha parameter a bit more robust (espicially if you change the energy functional around).

2) I use F instead of (-F) because my SDF is upside down from the Chan-Vese implementation.

BZF: The phi_x^2 and phi_y^2 are part of the definition of Gaussian Curvature. They come out when you do the Calculus of Variations to minimize the arclength of a curve.

8. Shawn Lankton says:

Alex: The demo sets the initialization as a box, but for most applications you will want to set the initial shape to something that is relevant.

Just pass the function a matrix of 1’s and 0’s where 1 is a guess at the foreground and 0 is a guess at the background.

9. Shawn Lankton says:

3D codes are coming soon!

10. richer says:

Dear shawn,

I have visit your homepage, and get localized active contours code in your paper “Localizing region-based active contours”. I think it is a good idea to deal with heterogeneous image.

I write this letter to you because I have some question to ask you about your code in the integral of local force in Eq.(14) in your paper “Localizing region-based active contours”.

I really cannot understand the integral about the y in your matlab code -(u-v).*(2.*I(idx)-u-v) for chan-vese model.

11. Shawn Lankton says:

richer: In the Matlab codes, the ‘x’ and ‘y’ variables from the paper aren’t easy to see because I use colon (:) notation in the Matlab instead of indexes. It would be more apparent in C++ code.

12. jf.garamendi says:

Dear Shawn,
Thanks for your contribution, it works really well.

I have a question for you:

In the paper of chan-vese (‘Active contours without edges’) they use the following curvature term:

but I don’t understand why you have used other expression.

Thanks

13. John says:

jf.garamendi, when you expand “div( gradient(phi) / |gradient(phi)| )” you will get exactly what is the last line of get_curvature function.

14. yyz says:

I have tried the algorithm,and it doesn’t work well in the hold case, how could i solve this problem with your codes? thanks

15. yyz says:

ps: hole case means the object have a hold within its boundary

16. Mark says:

Hi. Am trying to convert your code to java. Was wondering if you could explain what the bwdist function does. Does it compute the distance from each pixel to he next or does it find the nearest neighbouring pixel and then find the distance between them

17. Jack cc says:

In the paper of MS Energy part Eq(17)
It looks as:
[(I-u)^2 / Au] – [(I-v)^2 / Av]

And in your matlab code it shows
F = -((u-v).*((I(idx)-u)./Ain+(I(idx)-v)./Aout))
just like
[(I-u)*(v-u) / Au] – [(I-v)*(u-v)] / Av]

I really cannot understand if that’s right or not.

18. Jack cc says:

I got it, sorry!!

19. Nyan Khin says:

I am using your Active Contours Without Edges program.

Just wanted to so it had helped alot with my thesis and is a brilliant piece of work!

Many thanks for publishing it.

20. Mewada Hiren K says:

Dear Sir,
I am persuing Ph D from India. I am doing the work in inthe same field.Will you please give me the matlab code for localizing region based active contour using local histogram separation energy measurement.

Thanking You,

21. Shawn Lankton says:

All of the codes will be made available after my defense (September ’09). In the meanwhile, please see this post on sparse field active contours for a much faster active contour implementation.

22. shanka says:

i like to work on active contours for biomedical images. will you suggest where to and with what to start. i mean fundamentals.

with regards,

shanka

23. shanka says:

to add to the above, i feel very difficult to get into theory, pls help me.

shanka

24. Flo says:

Dear Shawn,

thanks a lot for this toolbox. I have a few questions about the finite differences used to compute the curvature, function curvature = get_curvature(phi,idx) (these questions are certainly very basic !):
1. for the first order central differences, phi_x and phi_y, why don’t you divide by 2 ?
2. Where does the phi_xy expression come from ? I suppose you derive phi_x against y, using again the central difference ? If so, are you sure about the sign of phi_xy (I would take the opposite) and is the coefficient 0.25 consistent with the absence of the coefficient 0.5 in the expressions of phi_x and phi_y ? If not, could you explain me how you get this expression?
3. I am not convinced either about the multiplying term “(phi_x2 + phi_y2).^(1/2)” in the calculus of the curvature (div(grad(phi)/|phi|)). Could you give us any reference ?