Home > Matlab, Vision > Active Contours

Active Contours

May 15th, 2007

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!

  1. Tran
    May 4th, 2008 at 03:41 | #1

    Very good.Have you done in 3D?

  2. April K
    September 1st, 2008 at 22:59 | #2

    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.
    April K

  3. bzf
    September 3rd, 2008 at 03:43 | #3

    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.


  4. bzf
    September 3rd, 2008 at 03:48 | #4

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

  5. April K
    September 3rd, 2008 at 10:37 | #5

    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
    September 3rd, 2008 at 12:05 | #6


    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.


  7. September 8th, 2008 at 23:13 | #7

    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. September 8th, 2008 at 23:15 | #8

    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. September 8th, 2008 at 23:15 | #9

    3D codes are coming soon!

  10. richer
    October 22nd, 2008 at 08:42 | #10

    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.

    I look forward your relpy.

    Thanks in advance!

  11. October 27th, 2008 at 17:37 | #11

    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. November 7th, 2008 at 13:04 | #12

    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:

    div( gradient(phi) / |gradient(phi)| )

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


  13. John
    January 6th, 2009 at 18:40 | #13

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

  14. February 4th, 2009 at 04:04 | #14

    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. February 4th, 2009 at 04:08 | #15

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

  16. Mark
    March 3rd, 2009 at 10:49 | #16

    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
    March 24th, 2009 at 03:23 | #17

    Hi,I’ve read your papers“Active Contours Without Edges,”and have some confused.

    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.
    I look forward your relpy.
    Thanks in advance!

  18. Jack cc
    March 24th, 2009 at 03:36 | #18

    I got it, sorry!!

  19. Nyan Khin
    April 30th, 2009 at 15:47 | #19

    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
    June 29th, 2009 at 06:14 | #20

    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,

    Hiren Mewada

  21. June 29th, 2009 at 08:18 | #21

    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
    September 7th, 2009 at 11:07 | #22

    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,


  23. shanka
    September 7th, 2009 at 11:12 | #23

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


  24. Flo
    October 16th, 2009 at 09:54 | #24

    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 ?

    Many thanks for your help,


  25. October 20th, 2009 at 10:03 | #25

    @Flo Great questions, and some are bugs!
    Please check the newest (fastest, most correct) implementation found here:

  1. October 10th, 2014 at 02:42 | #1
  2. November 13th, 2014 at 03:04 | #2
Comments are closed.