Академический Документы
Профессиональный Документы
Культура Документы
labeling - algorithms in
Mathematica, Java, C++
and C#.
Mariusz Jankowski
Department of Electrical Engineering,
University of Southern Maine, USA
mjankowski@usm.maine.edu
Jens-Peer Kuska
Department for Computer Graphics and
Image Processing, University of Leipzig,
Germany
kuska@informatik.uni-leipzig.de
2 Chapter Title
1. Abstract
A variety of region labeling algorithms have been described in the literature. In this paper we will
demonstrate Mathematica implementations of selected algorithms. Several alternative
implementations will be presented. The unique contribution of this paper lies in a detailed
discussion of realizations of a selected algorithm in several compiled languages and their
performance comparison. The languages include C++, Java, and C#.
Finding the connected components in a binary image can be done in several different ways [ Haralick
1992, Glassner 2001, Rosenfeld 1966]. The simplest method is to iteratively replace each label with the
minimum of it's 8-connected neighborhood [Haralick 1992]. The algorithm begins with an initial
labeling of all 1-pixels and ends when no more replacements can be made. It has a very simple
Mathematica implementation.
Chapter Title 3
The next algorithm is basically a float-fill algorithm [Glassner 2001]. The image is scanned until a
foreground pixel is found. An unlabeled foreground pixel is marked with a new label and its
position is pushed on a stack. While the stack is not empty the pixels on the stack are marked with
the label and the neighbor pixels are pushed on the stack. When the stack is empty the search
continues for the next seed point for the float-fill. The implementation in Mathematica is simple.
The labelComponentsStack[] function takes the binary image img (with zero boundary to
avoid the tests for the boundary in the inner loops) and the neighborhood positions nncell as
arguments.
4 Chapter Title
H∗ no foreground pixel ∗L
Do@
8k, Length@nncellD<D;
D;
H∗ increment the label ∗L
8j, 2, nc − 1<D,
label ++,
8i, 2, nr − 1<
D;
D
g
The main disadvantage of this algorithm is the fact, that the stack can become very large. For
two-dimensional pictures this is typical not a problem but for three-dimensional binary data it can
be. However, the algorithm is simple to implement in most programming languages.
The third algorithm [Rosenfeld 1966] avoids the usage of a stack and the global operation of the
float-filling. The algorithm needs two scans over the image. In the first scan one looks for
foreground pixels. If a foreground pixel is found the two previously scanned pixels in a 4-connected
Chapter Title 5
neighborhood or four pixels in an 8-connected neighborhood (Figure 1) are looked up for an already
assigned label.
pi-1, j pi, j
If the neighborhood contains no labeled pixels a new label is generated and assigned to the actual
pixel. If the neighborhood contains a single labeled pixel the found label is assigned to the pixel. If
the neighborhood contain more than a single label, one of the labels is used for the pixel and the
equivalence relation is recorded.
labelComponentsTwoPass@img_, nncell_D :=
H∗ no foreground pixel ∗L
Do@
If@Length@uD 1,
gD
6 Chapter Title
With the binary image in Figure 2, the first pass generates four labels and produces the labeled
image shown together with the equivalence relations 2 ñ 3 and 3 ñ 4.
Figure 2. A binary image (left) and labeled image (right), after initial labeling.
The next step is to resolve the equivalence relations to the rules that label 3 can be replaced with
label 2 and that label 4 can be replaced by label 2. When the replacement rules are found we can
apply these rules in the second pass and obtain the complete labeled image. The main problem here
is to resolve the equivalence relations. There are two standard ways to represent equivalence
relations: as a list of equivalence pairs (adjacency list) or as a matrix (adjacency matrix). The former
representation leads to a solution based on elementary graph search algorithms, as the equivalence
relations are simply a form of an undirected graph [Cormen 1990]. Several very fast Mathematica
realizations of a such an algorithm were recently posted on the Mathematica newsgroup [MathGroup].
The adjacency matrix algorithm is as follows [Gonzalez 1992]. Given equivalence relations with n
labels, a boolean n µ n matrix B is created with a True value at each position defined by an
equivalence relation k ñ l and False otherwise. The matrix is symmetric because the equivalence is
transitive and has True on the main diagonal because every label is equivalent to itself. To resolve
all equivalences one has to build the transitive closure matrix B+ which is given by
B+ = B fi B B fi B B B fi … fi Bn (Eq. 1)
The multiplication is standard matrix multiplication with element-wise logical fl. The most efficient
way to compute B+ is the Warshall algorithm [Warshall 1962]. Using Mathematica's sparse matrix
technique, with 1 for True and 0 for False, the Warshall algorithm can be implemented as
transitiveClosure@b_D :=
Do@
If@1 closure@@i, jDD,
D
closure
The equivalences are extracted from the transient closure B+ with the function
findEquivalence [2].
Chapter Title 7
findEquivalence@closure_D :=
The result will be a list of Mathematica replacement rules that can be used to update the labels in the
image form the first pass to the final labeled image. The final image is shown in Figure 3 (also in
pseudo-color).
In this section we turn our attention to the stack-based implementation in order to demonstrate and
compare fast realizations using pure Mathematica code and three compiled languages: C++, C#, and
Java.
The Mathematica Compile function can be used very effectively to speed up computations of the
type presented here. The code is translated into a simple register-based assembly language for a
virtual machine that is interpreted by the kernel. This code executes faster because it avoids the
main evaluation loop and is particularly effective when machine-precision numerical calculations
need to be executed a large number of times [Wagner 1996]. Many built-in Mathematica functions
themselves use Compile.
Compilation may improve processing speed by about a factor of 10, but sometimes even this is not
sufficient. To achieve greater processing speeds it is necessary to make calls to functions written in
compiled languages, such as C. Historically this has been accomplished by utilizing MathLink, the
cross-platform communication protocol defined by Wolfram Research, Inc [Wagner 1996, Wolfram
1999]. There is an extensive body of literature on the subject of using MathLink to call user-written
C or C++ functions or pre-existing scientific application libraries. We will not repeat the details here
due to space limitations and the fact that recent MathLink extensions have significantly simplified
the traditional process of calling external functions from Mathematica. These extensions, built on a
MathLink foundation are J/Link and .NET/Link introduced in versions 4 and 5 of Mathematica,
respectively. These add-ons give the Mathematica user unprecedented freedom in selecting the best
possible implementation for their high performance computing needs.
We begin with a Java implementation of the stack-based labeling algorithm. This loads the J/Link
add-on, launches the Java runtime and appends the Java class path with the location of our
user-defined classes.
Needs@"JLink`"D
InstallJava@D;
The following loads the Java class and instantiates the LabelImage object. This makes all the
public methods (i.e., functions) of the class available to the user and the Mathematica kernel.
javaObj = JavaNew@"LabelImage"D;
The class has a single method, labelImage that takes two arguments, the source image in the
form of a 2D array of integers and an integer specifying the desired size of the stack. It returns the
labeled image in the form of a 2D array of integers. The Java source code for the LabelImage
class is shown below.
/*
* LabelImage.java
*
* Created on April 16, 2004, 1:59 PM
*/
Chapter Title 9
if (img[r][c] == 0) continue ;
if (label[r][c] > 0) continue ;
/* encountered unlabeled foreground pixel at position r, c */
/* push the position on the stack and assign label */
stack.push(new int [] {r, c}) ;
label[r][c] = lab ;
} /* end while */
lab++ ;
}
return label ;
}
The method labelImage is now available for use as any Mathematica built-in or user-defined
function. Here is an example binary array.
i
j y
z
j
j z
z
j z
0 0 0 0 0
j
j z
z
j
j z
z
MatrixFormAimg = j z
0 0 1 1 0
j
j z
zE;
j
j z
z
j z
0 0 0 1 0
j
j z
z
j z
0 1 0 1 0
k0 0 0 0 0 {
i
j y
z
j
j z
z
j z
0 0 0 0 0
j
j z
z
j
j z
z
j z
0 0 1 1 0
j
j z
z
j
j z
z
j z
0 0 0 1 0
j z
k0 {
0 2 0 1 0
0 0 0 0
.NET/Link integrates Mathematica with Microsoft's .NET platform in much the same way J/Link
integrates with Java. .NET is a new development platform for Windows programming. It's
attractiveness to the Mathematica user comes from the fact that it supports code development in any
Chapter Title 11
language with a .NET compiler, including the widely used C++ and C#, a new language that is
similar in many ways to Java.
Needs@"NETLink`"D
InstallNET@D;
NETAssembly@LabelImage, 1D
netObj = NETNew@"LabelImage.LabelImage"D;
using System;
namespace LabelImage
{
/// <summary>
/// Summary description for LabelImage.
/// </summary>
///
.
.
.
public class LabelImage
{
public static Wolfram.NETLink.Expr floatfill(int ny,int nx,int []
data,int thres)
{ IntegerImage src, label;
int i,j,k,ii,jj;
Stack stack;
int labelNo=1;
Wolfram.NETLink.Expr toMath, symbolList;
src.set(i+1,j+1,data[k++]);
src.binarize(thres);
stack.push(ii-1,jj+1);
label.set(ii-1,jj+1,labelNo);
}
} // end while
labelNo++;
}
symbolList=new
Wolfram.NETLink.Expr(Wolfram.NETLink.ExpressionType.Symbol,"List");
toMath=new
Wolfram.NETLink.Expr(symbolList,labelNo-1,label.toMatrix());
return toMath;
}
}
i
j y
z
j
j z
z
j
j z
z
0 0 0 0 0
j
j z
z
j
j z
z
0 0 1 1 0
j
j z
z
j
j z
z
j z
0 0 0 1 0
j z
k0 {
0 2 0 1 0
0 0 0 0
4. Results
In this section, we present timing data for all the realizations of the stack-based algorithm discussed
in the previously. This loads the Digital Image Processing application package.
<< ImageProcessing`
dataPath =
ToFileName@8$HomeDirectory, "My Documents", "Data"<D;
img = Threshold@ImageRead@
ToFileName@dataPath, "Einstein.tif"DD, 127D;
This compares the speed of un-compiled and compiled evaluations of the labeling algorithm written
in Mathematica.
14 Chapter Title
0.2187500 Second
This creates a "look-up table" from a list of the primary and secondary colors. The list lut is
simply a list of replacement rules formed by a cyclic repetition of the selected colors. The length of
the list is determined by the number of labels.
Here we show the original binary image and the labeled image, pseudo-colored using look-up table
lut.
<< Graphics`
In what follows we present timing results obtained by running four versions of the connected
components stack-based algorithm for four different image sizes. The four code versions include
compiled Mathematica, C++, C#, and Java, while the chosen data dimensions are: 256 µ 256,
512 µ 512, 1 K µ 1 K, and 2 K µ 2 K. Each recorded timing value reflects an average of 20 runs for
each combination of language and image dimension. This shows the raw results.
Chapter Title 15
15000
Intel C 7.01
12500
Intel C#
10000
Java
7500
Mathematica
5000
2500
0
2562 5122 10242 20482
Figure 4. Timing results (in milliseconds) of four different realizations of region labeling algorithm.
Here is an alternative view of the same timing data. The following bar chart shows timing results
normalized with respect to compiled Mathematica speed and averaged over the four dimensions of
the example image.
16 Chapter Title
0.8
0.6
0.4
0.2
0
C++ C# Java Mathematica
Figure 5. Relative timing results for four different realizations of region labeling algorithm (Mathematica = 1.0).
5. Summary
In this paper we investigated the execution speed of three compiled languages and Mathematica
using a non-trivial algorithm of practical importance in digital image processing. The region
labeling algorithm we present is interesting for two reasons, it plays a prominent role in image
analysis and it has behavioral features that make it difficult for interpreted languages such as
Mathematica to implement efficiently. The chosen compiled languages are all naturally supported
by MathLink and its recent extensions, J/Link and NET/Link. As has been demonstrated, linking to
external code has been made especially simple in the recent editions of Mathematica, therefore
allowing any user to benefit from the performance advantages of compiled languages. Our results
confirm that the C++/MathLink combination remains the fastest alternative to pure Mathematica
development. However, we also found Java and J/Link to be only 20% - 60% slower then C++. This
peformance difference should be carefully weighed against the benefits of a significantly simpler
interface between Mathematica and Java and greater portability.
6. References
[Haralick 1992] Haralick, R.M., Shapiro, L.G., "Computer and Robot Vision," Volume 1,
Addison-Wesley, 1992.
[Glassner 2001] Glassner, A., "Fill 'Er Up!", IEEE Computer Graphics and Applications, 2001, Vol.
21 No. 1; Jan. / Feb. 2001, pp. 78-85.
Chapter Title 17
[Rosenfeld 1966] Rosenfeld, A., Pfalz, J. L., "Sequential Operations in Digital Picture Processing,"
Journal of the ACM, Vol. 13, No. 4, October 1966, pp. 471-494.
[Cormen 1990] Cormen, H., Leiserson, C., and Rivest, R., "Introduction to Algorithms," MIT Press,
1990.
[MathGroup] http://forums.wolfram.com/mathgroup/archive/2004/Feb/ - see thread: "Re:
Computing sets of equivalences".
[Gonzalez 1992] Gonzales, R. C., Woods, R. E., "Digital Image Processing," Addison Wesley, 1992.
[Warshall 1962] Warshall, S., "A Theorem on Boolean Matrices," Journal of the ACM, Vol. 9, No.
1, Jan 1962, pp.11-12.
[Wagner 1996] Wagner, D., "Power programming with Mathematica," McGraw-Hill, 1996.
[Wolfram 1999] Wolfram, S., "The Mathematica Book," Fourth Edition, Wolfram Research, 1999.