1 /************************************************************************/
2 /* */
3 /* Copyright 2004 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35
36 #include <iostream>
37 #include "vigra/unittest.hxx"
38 #include "vigra/stdimage.hxx"
39 #include "vigra/multi_morphology.hxx"
40 #include "vigra/linear_algebra.hxx"
41 #include "vigra/matrix.hxx"
42
43 using namespace vigra;
44
45 struct MultiMorphologyTest
46 {
47 typedef vigra::MultiArray<3,int> IntVolume;
48 typedef vigra::MultiArray<2,int> IntImage;
49
MultiMorphologyTestMultiMorphologyTest50 MultiMorphologyTest() :
51 img(IntImage::difference_type(7,7)),
52 img2(IntImage::difference_type(7,7)),
53 lin(IntImage::difference_type(7,1)),
54 vol(IntVolume::difference_type(5,5,5))
55 {
56 static const unsigned char in[] = {
57 0, 1, 1, 1, 1, 1, 0,
58 0, 1, 1, 1, 1, 1, 0,
59 0, 1, 1, 1, 1, 1, 0,
60 0, 1, 1, 1, 1, 1, 0,
61 0, 1, 1, 1, 1, 1, 0,
62 0, 1, 1, 1, 1, 1, 0,
63 0, 1, 1, 1, 1, 1, 0};
64
65 const unsigned char *i=in;
66 for(IntImage::iterator iter=img.begin(); iter!=img.end(); ++iter, ++i){
67 *iter=*i;
68 }
69 static const unsigned char in1d[] = {0, 1, 1, 1, 1, 1, 0};
70 i=in1d;
71 for(IntImage::iterator iter=lin.begin(); iter!=lin.end(); ++iter, ++i){
72 *iter=*i;
73 }
74
75 static const unsigned char in1[] = {
76 0, 1, 2, 3, 4, 5, 6,
77 0, 1, 2, 3, 4, 5, 6,
78 0, 1, 2, 3, 4, 5, 6,
79 0, 1, 2, 3, 4, 5, 6,
80 0, 1, 2, 3, 4, 5, 6,
81 0, 1, 2, 3, 4, 5, 6,
82 0, 1, 2, 3, 4, 5, 6};
83
84 i=in1;
85 for(IntImage::iterator iter=img2.begin(); iter!=img2.end(); ++iter, ++i){
86 *iter=*i;
87 }
88
89 static const unsigned char in2[] = { 0, 0, 0, 0, 0,
90 0, 0, 0, 0, 0,
91 0, 0, 0, 0, 0,
92 0, 0, 0, 0, 0,
93 0, 0, 0, 0, 0,
94
95 0, 0, 0, 0, 0,
96 0, 1, 1, 1, 0,
97 0, 1, 1, 1, 0,
98 0, 1, 1, 1, 0,
99 0, 0, 0, 0, 0,
100
101 0, 0, 0, 0, 0,
102 0, 1, 1, 1, 0,
103 0, 1, 1, 1, 0,
104 0, 1, 1, 1, 0,
105 0, 0, 0, 0, 0,
106
107 0, 0, 0, 0, 0,
108 0, 1, 1, 1, 0,
109 0, 1, 1, 1, 0,
110 0, 1, 1, 1, 0,
111 0, 0, 0, 0, 0,
112
113 0, 0, 0, 0, 0,
114 0, 0, 0, 0, 0,
115 0, 0, 0, 0, 0,
116 0, 0, 0, 0, 0,
117 0, 0, 0, 0, 0};
118
119 i=in2;
120 for(IntVolume::iterator iter=vol.begin(); iter!=vol.end(); ++iter, ++i){
121 *iter=*i;
122 }
123 }
124
binaryErosionTestMultiMorphologyTest125 void binaryErosionTest()
126 {
127 IntImage res(img);
128 int foreground = NumericTraits<int>::one();
129
130 static const int desired[] = {
131 0, 0, 0, foreground, 0, 0, 0,
132 0, 0, 0, foreground, 0, 0, 0,
133 0, 0, 0, foreground, 0, 0, 0,
134 0, 0, 0, foreground, 0, 0, 0,
135 0, 0, 0, foreground, 0, 0, 0,
136 0, 0, 0, foreground, 0, 0, 0,
137 0, 0, 0, foreground, 0, 0, 0};
138
139 multiBinaryErosion(srcMultiArrayRange(img), destMultiArray(res), 2);
140 shouldEqualSequence(res.begin(), res.end(), desired);
141
142 res = 0;
143 multiBinaryErosion(img, res, 2);
144 shouldEqualSequence(res.begin(), res.end(), desired);
145 }
146
binaryErosionTest2MultiMorphologyTest147 void binaryErosionTest2()
148 {
149 IntImage res(img2);
150 int foreground = NumericTraits<int>::one();
151
152 static const int desired[] = {
153 0, 0, 0, foreground, foreground, foreground, foreground,
154 0, 0, 0, foreground, foreground, foreground, foreground,
155 0, 0, 0, foreground, foreground, foreground, foreground,
156 0, 0, 0, foreground, foreground, foreground, foreground,
157 0, 0, 0, foreground, foreground, foreground, foreground,
158 0, 0, 0, foreground, foreground, foreground, foreground,
159 0, 0, 0, foreground, foreground, foreground, foreground};
160
161 multiBinaryErosion(img2, res, 2);
162 shouldEqualSequence(res.begin(), res.end(), desired);
163 }
164
binaryErosionTest1DMultiMorphologyTest165 void binaryErosionTest1D()
166 {
167 IntImage res(lin);
168 int foreground = NumericTraits<int>::one();
169
170 static const int desired[] = {0, 0, 0, foreground, 0, 0, 0};
171 multiBinaryErosion(lin, res, 2);
172 shouldEqualSequence(res.begin(), res.end(), desired);
173 }
174
binaryErosionAndDilationTest3DMultiMorphologyTest175 void binaryErosionAndDilationTest3D()
176 {
177 IntVolume res(vol.shape()), res2(vol.shape());
178 int f = NumericTraits<int>::one();
179
180 static const int desiredErosion[] = { 0, 0, 0, 0, 0,
181 0, 0, 0, 0, 0,
182 0, 0, 0, 0, 0,
183 0, 0, 0, 0, 0,
184 0, 0, 0, 0, 0,
185
186 0, 0, 0, 0, 0,
187 0, 0, 0, 0, 0,
188 0, 0, 0, 0, 0,
189 0, 0, 0, 0, 0,
190 0, 0, 0, 0, 0,
191
192 0, 0, 0, 0, 0,
193 0, 0, 0, 0, 0,
194 0, 0, f, 0, 0,
195 0, 0, 0, 0, 0,
196 0, 0, 0, 0, 0,
197
198 0, 0, 0, 0, 0,
199 0, 0, 0, 0, 0,
200 0, 0, 0, 0, 0,
201 0, 0, 0, 0, 0,
202 0, 0, 0, 0, 0,
203
204 0, 0, 0, 0, 0,
205 0, 0, 0, 0, 0,
206 0, 0, 0, 0, 0,
207 0, 0, 0, 0, 0,
208 0, 0, 0, 0, 0};
209
210 multiBinaryErosion(vol, res, 1);
211 shouldEqualSequence(res.begin(), res.end(), desiredErosion);
212
213 static const int desiredDilation[] = { 0, 0, 0, 0, 0,
214 0, 0, 0, 0, 0,
215 0, 0, 0, 0, 0,
216 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0,
218
219 0, 0, 0, 0, 0,
220 0, 0, 0, 0, 0,
221 0, 0, f, 0, 0,
222 0, 0, 0, 0, 0,
223 0, 0, 0, 0, 0,
224
225 0, 0, 0, 0, 0,
226 0, 0, f, 0, 0,
227 0, f, f, f, 0,
228 0, 0, f, 0, 0,
229 0, 0, 0, 0, 0,
230
231 0, 0, 0, 0, 0,
232 0, 0, 0, 0, 0,
233 0, 0, f, 0, 0,
234 0, 0, 0, 0, 0,
235 0, 0, 0, 0, 0,
236
237 0, 0, 0, 0, 0,
238 0, 0, 0, 0, 0,
239 0, 0, 0, 0, 0,
240 0, 0, 0, 0, 0,
241 0, 0, 0, 0, 0};
242
243 IntVolume v2(res);
244
245 multiBinaryDilation(v2, res, 1);
246 shouldEqualSequence(res.begin(), res.end(), desiredDilation);
247
248 multiBinaryDilation(v2, res2, 1.8);
249 shouldEqualSequence(res2.begin(), res2.end(), vol.begin());
250 }
251
grayErosionTest2DMultiMorphologyTest252 void grayErosionTest2D()
253 {
254 typedef vigra::MultiArray<2,float> FloatImage;
255 FloatImage in(img), res(img), res_cmp(img);
256
257 //erosion on original image
258 multiGrayscaleErosion(srcMultiArrayRange(in), destMultiArray(res), 1);
259
260 //create comparable result = result+2 for every pixel
261 for(FloatImage::iterator iter=res.begin(); iter!=res.end(); ++iter){
262 *iter+=2.9f;
263 }
264
265 //create compare image = img+2 for every pixel
266 for(FloatImage::iterator iter=in.begin(); iter!=in.end(); ++iter){
267 *iter+=2.9f;
268 }
269 //erosion on compare image (image+2)
270 multiGrayscaleErosion(in, res_cmp, 1);
271
272 shouldEqualSequence(res.begin(), res.end(), res_cmp.begin());
273 }
274
grayDilationTest2DMultiMorphologyTest275 void grayDilationTest2D()
276 {
277 typedef vigra::MultiArray<2,float> FloatImage;
278 FloatImage in(img), res(img), res_cmp(img);
279
280 //dilation on original image
281 multiGrayscaleDilation(srcMultiArrayRange(in), destMultiArray(res), 1);
282
283 //create comparable result = result+2 for every pixel
284 for(FloatImage::iterator iter=res.begin(); iter!=res.end(); ++iter){
285 *iter+=2.9f;
286 }
287
288 //create compare image = img+2 for every pixel
289 for(FloatImage::iterator iter=in.begin(); iter!=in.end(); ++iter){
290 *iter+=2.9f;
291 }
292 //dilation on compare image (image+2)
293 multiGrayscaleDilation(in, res_cmp, 1);
294
295 shouldEqualSequence(res.begin(), res.end(), res_cmp.begin());
296 }
297
grayErosionAndDilationTest2DMultiMorphologyTest298 void grayErosionAndDilationTest2D()
299 {
300 typedef vigra::MultiArray<2, float> FloatImage;
301 FloatImage in(img), di_res(img), er_res(img);
302
303 //erosion on original image
304 multiGrayscaleErosion(in, er_res, 1);
305 //dilation on original inverted image
306 for(FloatImage::iterator iter=in.begin(); iter!=in.end(); ++iter){
307 *iter*=-1.0f;
308 }
309 multiGrayscaleDilation(in, di_res, 1);
310 //Invert dilation res
311 for(FloatImage::iterator iter=di_res.begin(); iter!=di_res.end(); ++iter){
312 *iter*=-1.0f;
313 }
314
315 shouldEqualSequence(di_res.begin(),di_res.end(), er_res.begin());
316 }
317
grayClosingTest2DMultiMorphologyTest318 void grayClosingTest2D()
319 {
320 typedef vigra::MultiArray<2,UInt8> UInt8Image;
321 UInt8Image in(img), tmp(img), res(img);
322
323 //erosion on original image
324 multiGrayscaleErosion(srcMultiArrayRange(in), destMultiArray(tmp),2);
325 multiGrayscaleDilation(srcMultiArrayRange(tmp), destMultiArray(res),2);
326 }
327
328 IntImage img, img2, lin;
329 IntVolume vol;
330 };
331
332
333 struct MorphologyTestSuite
334 : public vigra::test_suite
335 {
MorphologyTestSuiteMorphologyTestSuite336 MorphologyTestSuite()
337 : vigra::test_suite("MorphologyTestSuite")
338 {
339 add( testCase( &MultiMorphologyTest::binaryErosionTest));
340 add( testCase( &MultiMorphologyTest::binaryErosionTest2));
341 add( testCase( &MultiMorphologyTest::binaryErosionTest1D));
342 add( testCase( &MultiMorphologyTest::binaryErosionAndDilationTest3D));
343 add( testCase( &MultiMorphologyTest::grayErosionTest2D));
344 add( testCase( &MultiMorphologyTest::grayDilationTest2D));
345 add( testCase( &MultiMorphologyTest::grayErosionAndDilationTest2D));
346 add( testCase( &MultiMorphologyTest::grayClosingTest2D));
347 }
348 };
349
main(int argc,char ** argv)350 int main(int argc, char ** argv)
351 {
352 MorphologyTestSuite test;
353
354 int failed = test.run(vigra::testsToBeExecuted(argc, argv));
355
356 std::cout << test.report() << std::endl;
357 return (failed != 0);
358 }
359
360