No BSD License  

Highlights from
GeoML

image thumbnail

GeoML

by

 

28 Aug 2008 (Updated )

A general morphable template tool for image segmentation.

GeoML: intro

GeoML: intro

GeoML is a Java library for constrained geometry, it allows to describe
a geometric model in XML, as an example an ellips can be described as
follows:
       <?xml version="1.0" encoding="ISO-8859-1"?>
       <!DOCTYPE model SYSTEM "GeoML-v01.dtd">
       <model name="ellipse">
         <!-- Free parameters -->
         <number name="A" value="1"/>
         <number name="B" value="2"/>
         <number name="phi" value="0"/>
         <number name="dx" value="0"/>
         <number name="dy" value="0"/>
         <!-- The center: -->
         <point name="c" x="0" y="0" visible="false"/>
         <!-- The circle: -->
         <circle name="ellipse" center="c" radius="1"/>
         <!-- The transformation: -->
         <rototranslation name="rototransl" scalex="A"
             scaley="B" x="dx" y="dy" angle="phi"/>
         <transform name="ellipse" transformation="rototransl"/>
       </model>
In a GoML model there are:
 parameter elements:     numbers ad plain numbers, ranges, etc.
 geometrical elements:   points, lines, circles, curves, etc.
 computation elements:   transformations, equations, ecc.
each element has a set of attributes describing how it must be created.
For a better documentation see libs/ActiveTemplates/doc... or read the
source code libs/ActiveTemplates/src ;)
Once a model is defined, put it in a reachable directory (with the DTD
GeoML-v01.dtd) and use it by the given Matlab functions "GeoML*".
A geometric model can be used to generate curves and to discretize them
in sets of points, these points can be used to compute an energy function
on an image; the minimization of the energy function depending on the
values of the parameters (the number elements) morphs the model adapting
it to the objects in the image. Let's try it!!!
Note.. that a simple model viewer and "deformer" can be found in
"lib/ActiveTemplates" in "src" and "classes" as the class
"com.dsi.libs.geoml.terminals.GeoMLModelViewer". For unix/linux users,
in the directory "lib" a BASH executable script "GeoMLViewer.sh" can be
found, for Windows users the file is "GeoMLViewer.bat".

Contents

Loading the tools:

To let the code work properly, take the files "*.jar" placed in the
directory "lib", and put them in a reachable directory (as an example
"/usr/java/lib"), type in Matlab:

> edit classpath.txt

and add the references to the libs:

   ...
   /usr/java/lib/jep.jar
   /usr/java/lib/djep.jar
   /usr/java/lib/Jama.jar
   /usr/java/lib/GeoML.jar

then restart Matlab so that it can load the listed Java libs.

The following code adds to the matlab path the M-Files directories only
if required.
% Olny if not jet done:
if exist('GeoMLParseModel','file')~=2
    % Load the 'mtools' M-Files:
    addpath(genpath('mtools'));
end

Loading a model:

At first, load a GeoML model using "GeoMLParseModel". This gives you two
things: the GeoML model as a Java instance of the class
"com.dsi.libs.geoml.Group", and a set of free variables in an array and
in a struct where the fields have the same names of the variables.
% Loading a model:
[model,free,freeMap] = GeoMLParseModel('spirals');

% The free variables:
disp(fields(freeMap)');
    'x1'    'y1'    'x2'    'y2'    'x3'    'y3'    'x4'    'y4'    'dist'

Generating the discrete points set:

The model is useful only if points can be generated on an image, to do
that the function "GeoMLIterate" is provided.
% Iterating on the model to generate the points:
pts = GeoMLIterate(model);

% Take a look!
figure; plotpoints(pts,'r.');

Changing the model's variables:

The model is useful only if it can be morphed by changing the free
parameters and updating the whole geometry (including all levels of
dependency of the gemometrical elements one from each other). This can be
done using the "setValueUpdate" on the variables: this method changes the
value and then updates the whole model. Another possibility is to use the
method "setValue" for all the variables that must be updated, and then to
call "model.update" on the model to force the updating. These two
solutions are, from the computational complexity point of view, the same.
In the example the two parameters "true,'real'" are passed to
"GeoMLIterate". The first one say that the obtained points must be joined
in a single sequence (true), in fact it is possible to split them among
the geometrical structure of th model (the Group class instances). The
second one say that the discretization of points must generate the real
curves' coordinates, not the integer approximations generated to fit the
model in the pixels discretization of the image, this can change the
number of generated points.
% Changing the free variables:
freeMap.x4.setValueUpdate(20);
freeMap.y4.setValueUpdate(-20);

% Take a look!
pts = GeoMLIterate(model,true,'real');
figure; plotshape(pts,false,'r');

Model optimization: generating a test image

Let's work on model fitting: at first a test image is synthetized by
loading the model, setting the parameters, generating the points,
setting the corresponding pixels to white, filling the ellipse, and then
adding noise.
% Loading:
img = zeros(256,256);
[model,free,freeMap] = GeoMLParseModel('ellipse');

% Real image synthesis:
freeMap.dx.setValue(125);
freeMap.dy.setValue(125);
freeMap.A.setValue(100);
freeMap.B.setValue(50);
freeMap.phi.setValue(1);
model.update;
pts = GeoMLIterate(model);
ptsIdx = sub2ind(size(img),pts(2,:),pts(1,:));
img(ptsIdx) = 1;
img = bwfill(bwmorph(bwmorph(img,'dilate'),'thin',Inf),'holes');
img = imscale(gaussianFilter(img + randn(size(img))*0.1),[0.6,0.8]);

% Take a look!
figure; imshow(img);

Model optimization: initialization:

Let's set the initial parameters of the model to an acceptable initial
value, they can be obtained by image processing techniques, its only a
rough initialization that allows the optimization process to start from a
"good" position in the energy function.
% Setting parameters
freeMap.dx.setValue(120);
freeMap.dy.setValue(120);
freeMap.A.setValue(90);
freeMap.B.setValue(60);
freeMap.phi.setValue(1.1);
model.update;

% Take a look!
pts = GeoMLIterate(model,true,'real');
figure; imshow(img); hold on; plotshape(pts,false,'r');

Model optimization: the optimization process

The optimization process is based on an optimization algorithm (by
default fminsearch) and an energy function (here ATE_GradientNorm based
on the gradient's norm of the given image). In this example an iterative
optimization process is used with a little bit of randomizzation to
prevent to be stuch in local minima of the energy function, this is only
a rough algorithm, choosing carefully the optimization algorithm may be
better (from the performance point of view).
% Iterating on optimizations:
for i=1:10
    %  A random noise in the optimization process prevents to be stuch in
    % local minima positions of the energy function:
    freeMap.dx.setValueUpdate(freeMap.dx.getValue+randn);
    freeMap.dy.setValueUpdate(freeMap.dx.getValue+randn);
    % Optimizing:
    opt = ATOptimize(img,model,free,@ATE_GradientNorm);
end

% Take a look!
pts = GeoMLIterate(model,true,'real');
figure; imshow(img); hold on; plotshape(pts,false,'r');

Very complex models:

Very complex models can be defined with equations, transformations as
R2->R2 maps, geometrical constructions, locuses, procedures, recursion
and more!
% A very well-known fractal, the Koch's snowflake:
model = GeoMLParseModel('fractal');
pts = GeoMLIterate(model,true,'real');
figure; plotshape(pts,false,'r'); axis equal;

Contact us