A Matlab toolbox implementing Level Set Methods
Baris Sumengen,
Vision Research Lab at
UC Santa Barbara
This set of Matlab files implements Level Set Methods and follows
Osher and
Fedkiw's book. A combination of curvature-based forces, vector field-based
forces and forces in the normal direction can be used.
Download:
Download by clicking here. This package consist of a set of
m-files compressed into a zip file. Unzip them to a folder and then add this
folder to Matlab's path.
Any type of comments, bug reports, benchmarks, profiling efforts are highly
appreciated. Please send your comments to .
- I would be happy if you acknowledge this toolbox in your papers if you end up using it for your research.
Note: See also Ian Mitchell's
Matlab toolbox for Level Set
Methods for a different implementation of the same problem.
Note 2: See also
Gabriel Peyré's Matlab
toolbox for Fast Marching Methods. This uses a C implementation and .mex
files. Currently fast marching methods are not implemented in my toolbox but
will be soon.
Purpose: Creating a simple to use and understand implementation of
the Level Set Methods. Speed was not the main motivating point as much as
readability of the code. On the other hand, given Matlab's capabilities, this
toolbox should be reasonably fast (unintuitive Matlab tricks are avoided
intentionally to prevent confusion). It can be a good learning tool to
accompany
Osher and Fedkiw's book on Level Set Methods. Also it would be a good
template for a C or Java based implementation.
This toolbox in its current state can be used for implementing a 2-D curve
evolution or a diffusion of a 2-D function phi(x,y), e.g. anisotropic diffusion
on a gray-scale image.
Capabilities:
- This toolbox currently implements only a 2-D interface (curve) evolution.
Extending to 3-D interface (surface) evolution is trivial because of its
modular structure based on 1-D functions (I'll do this soon).
- 1st, 2nd and 3rd order accurate Essentially Non-Oscillatory (ENO) and 5th
order accurate Weighted ENO (WENO) are supported throughout the toolbox for
derivative calculations.
- A function for re-initialization of a signed distance function is provided
(reinit_SD).
- A high-level function (evolve2D) is provided that can utilize any
combination of: 1) a force in the normal direction to the curve, 2) a
curvature-based force, 3) evolution under the influence of an external vector
field.
Tutorial
Also see my power point presentation:
Overview of Level Set Methods and Image Segmentation
There are three m-files that needs to be talked about first:
reinit_SD(), evolve2D()
and test.m
test.m include a fully
working program that implements curve evolution: starts with a square shaped
curve and shrinks it under constant normal force.
The function evolve2D() is a high level
function that takes an input, evolves it N iterations and returns the result.
Here is the prototype and documentation for this function (taken from the
m-file):
function [phi] =
evolve2D(phi, dx, dy, iterations, accuracy, ...
is_signed_distance, normal_evolve, Vn,
vector_evolve, u, v, kappa_evolve, b)
Calculates evolution for a 2D curve (3D level set function) phi.
phi is the
input level
set function.
dx and dy are the resolution of the grid at x and y dimensions.
alpha is a constant for calculating the euler step (dt). Should
be between 0 and 1. 0.5 is quite safe whereas 0.9 can be risky.
iterations specifies the number of iterations before the function returns.
normal_evolve, vector_evolve, kappa_evolve should be either set to 0 and
1. This
indicates if these forces are present or not. If any of these are set to
1,
corresponding variables (e.g. Vn, u, v, b) should not be an empty array
[]. if
either normal_evolve or vector_evolve are set to 1, accuracy needs to be
specified,
otherwise accuracy can be set to an empty array. Allowed values for
accuracy are
'ENO1', 'ENO2', 'ENO3', 'WENO'. These correspond to 1st, 2nd, 3rd and 5th
order
accurate schemes for calculating the derivative of phi. if both normal_evolve and
vector_evolve are set to 1, then is_signed_distance needs to be specified.
If phi is
approximately a signed distance function, set this variable to 1. If
is_signed_distance == 1, Godunov scheme will be used, otherwise Stencil
Local
Lax-Friedrichs (SLLF) scheme will be used (See Osher&Fedkiw section 6.4).
Other variables (these are either a scalar or of the same size as phi):
Vn: Force in the normal direction.
u: x component of the vector field
v: y component of the vector field
b: this specifies the weighting for the curvature (always positive
everywhere).
|
The function reinit_SD() can be used for
re-initialization of a signed distance function. This function would be
especially effective if the input is not too far away from a signed distance
function.
function [phi] = reinit_SD(phi, dx, dy, alpha, accuracy,
iterations)
Reinitializes phi into a signed distance function while preserving
the zero level set (the interface or the curve).
dx and dy are the resolution of the grid at x and y
dimensions.
alpha is a constant for calculating the euler step (dt). Should
be between 0 and 1. 0.5 is quite safe whereas 0.9 can be risky.
iterations specifies the number of iterations before the function
returns.
accuracy is the order of accuracy of derivative calculation.
Allowed values for accuracy are 'ENO1', 'ENO2', 'ENO3', 'WENO'.
These correspond to 1st, 2nd, 3rd and 5th order accurate schemes
for calculating the derivative of phi.
|
evolve2D() does not call
reinit_SD() within itself (and as a result may
not preserve signed distance-ness of phi). On
the other hand, if desired, in an outside loop you can call
evolve2D() for 5-10 iterations followed by a
call to reinit_SD(), then call
evolve2D() again for 5-10 more iterations, etc.
Examples
Let us first start with a rectangular curve. This curve can be defined as the
boundary of the following binary function (or image, matrix) consisting of 1's
and -1's:
phi = ones(100,100);
phi(30:60,30:60) = -1;
We can think of the curve as the zero level set of this function (in
continuous domain): phi(x,y) == 0. As can be
seen, any function phi(x,y) whose zero level set
corresponds to this curve can be a representation of this curve. Since a signed
distance function will make life easier for us due to its smoothness, we would
like to create a function phi(x,y) such that
|phi(x,y)| = d, where d is the distance of (x,y) from the curve itself.
The sign is taken as (+) if (x,y) is outside the curve, (-) if (x,y) is inside
the curve. One way to create this signed distance function is calling
reinit_SD(), which will smooth phi using a
reinitialization PDE (see equations 7.4 and 7.5 in Osher&Fedkiw's book).
phi = reinit_SD(phi, dx, dy, 0.5, 'WENO', 200);
The following images show the progress of this function. As can be seen, the
corners of the curve are slightly smoothed but except that the zero level set of
phi is preserved during the diffusion.
Evolution of a binary function towards a signed
distance function under re-initialization PDE
 |
 |
| phi after 0 iterations |
curve (zero level set) after 0 iterations |
 |
 |
| phi after 30 iterations |
curve (zero level set) after 30 iterations |
 |
 |
| phi after 200 iterations |
curve (zero level set) after 200 iterations |
Since this process takes longer than necessary and smoothes the curve
slightly, we'll use for the rest of this discussion a different way of creating
this signed distance function. We will utilize Matlab's
bwdist() function.
phi = ones(100,100);
phi(30:60,30:60) = -1;
phi = double((phi > 0).*(bwdist(phi < 0)-0.5) - (phi < 0).*(bwdist(phi >
0)-0.5));
figure;surf(phi);
figure;contour(phi, [0 0], 'r');
Now we can start evolving this initial curve using the
evolve2D() function. Note that, phi does not
have to be a signed distance function, but if it is this increases the stability
and quality of the evolution (especially if a vector field-based force and a
force in normal direction are combined).
1) Shrinking the curve in the normal direction:
% Vn: force in the normal
direction
Vn = -0.2*ones(100,100);
dx=1;
dy=1;
figure;contour(phi, [0 0], 'b');
phi = evolve2D(phi,dx,dy,0.5,15,'ENO2',[],1,Vn,0,[],[],0,[]);
hold on;contour(phi, [0 0], 'r');hold off;axis equal;

2) Translating the curve using an external vector field
% External vector field
u = -0.5*(1/sqrt(2)).*ones(100,100); %x component
of the vector field
v = -0.5*(1/sqrt(2)).*ones(100,100); %y component of the
vector field
dx=1;
dy=1;
figure;contour(phi,[0 0],'b');
phi = evolve2D(phi,dx,dy,0.5,25,'ENO3',[],0,[],1,u,v,0,[]);
hold on;contour(phi,[0 0],'r'); hold off; axis equal;

3) Smoothing a curve under its curvature
% b: weighting for
curvature-based force. b needs to be positive
b = 0.3*ones(100, 100);
dx=1;
dy=1;
figure;contour(phi,[0 0],'b');
phi = evolve2D(phi,dx,dy,0.5,25,[],[],0,[],0,[],[],1,b);
hold on; contour(phi,[0 0],'r'); hold off; axis equal;

As can be seen, curvature of a straight line is 0, so only the corners are
smoothed.
4) Simultanous translation and expansion of the curve
% External vector field
u = -0.5*(1/sqrt(2)).*ones(100, 100); %x component
of the vector field
v = -0.5*(1/sqrt(2)).*ones(100, 100); %y component of the
vector field
% Vn: force in the normal direction
Vn = 0.2*ones(100, 100);
dx=1;
dy=1;
figure;contour(phi,[0 0],'b');
phi = evolve2D(phi,dx,dy,0.5,60,'ENO2',1,1,Vn,1,u,v,0,[]);
hold on; contour(phi,[0 0],'r'); hold off; axis equal;

5) Smoothing an image under the curvature of its level sets (Mean
curvature flow)
In this example, all level sets of the image are smoothed under
curvature-based forces.
Note that Matlab's contour function selects the levels automatically, so the
level sets displayed might not correspond to each other.
dx=1;
dy=1;
im = imread('retina.bmp');
phi = double(im(:,:,1));
figure; imagesc(phi); axis image; colormap gray;
figure; contour(phi); axis image;
% b:weighting for curvature-based force. b needs to be
positive
b = 0.3*ones(size(phi));
phi = evolve2D(phi,dx,dy,0.5,25,[],[],0,[],0,[],[],1,b);
figure; imagesc(phi); axis image; colormap gray;
figure; contour(phi); axis image;
Original Image

Level Sets of the original image

After 5 iterations of smoothing

Corresponding level sets (5 iterations)

After 25 iterations of smoothing

Corresponding level sets (25 iterations)

|