@@ -156,6 +156,9 @@ static MagickBooleanType ConnectedComponentsStatistics(const Image *image,
156
156
ssize_t
157
157
y ;
158
158
159
+ /*
160
+ Collect statistics on unique objects.
161
+ */
159
162
object = (CCObject * ) AcquireQuantumMemory (number_objects ,sizeof (* object ));
160
163
if (object == (CCObject * ) NULL )
161
164
{
@@ -235,6 +238,9 @@ static MagickBooleanType ConnectedComponentsStatistics(const Image *image,
235
238
}
236
239
component_view = DestroyCacheView (component_view );
237
240
image_view = DestroyCacheView (image_view );
241
+ /*
242
+ Report statistics on unique objects.
243
+ */
238
244
qsort ((void * ) object ,number_objects ,sizeof (* object ),CCObjectCompare );
239
245
(void ) fprintf (stdout ,
240
246
"Objects (id: bounding-box centroid area mean-color):\n" );
@@ -247,7 +253,7 @@ static MagickBooleanType ConnectedComponentsStatistics(const Image *image,
247
253
break ;
248
254
GetColorTuple (& object [i ].color ,MagickFalse ,mean_color );
249
255
(void ) fprintf (stdout ,
250
- " %.20g: %.20gx%.20g%+.20g%+.20g %+ .1f,%+ .1f %.20g %s\n" ,(double )
256
+ " %.20g: %.20gx%.20g%+.20g%+.20g %.1f,%.1f %.20g %s\n" ,(double )
251
257
object [i ].id ,(double ) object [i ].bounding_box .width ,(double )
252
258
object [i ].bounding_box .height ,(double ) object [i ].bounding_box .x ,
253
259
(double ) object [i ].bounding_box .y ,object [i ].centroid .x ,
@@ -257,12 +263,11 @@ static MagickBooleanType ConnectedComponentsStatistics(const Image *image,
257
263
return (status );
258
264
}
259
265
260
- static MagickBooleanType MergeConnectedComponents (const Image * image ,
261
- const Image * component_image ,const size_t number_objects ,
262
- const double area_threshold , ExceptionInfo * exception )
266
+ static MagickBooleanType MergeConnectedComponents (Image * image ,
267
+ const size_t number_objects ,const double area_threshold ,
268
+ ExceptionInfo * exception )
263
269
{
264
270
CacheView
265
- * component_view ,
266
271
* image_view ;
267
272
268
273
CCObject
@@ -277,6 +282,9 @@ static MagickBooleanType MergeConnectedComponents(const Image *image,
277
282
ssize_t
278
283
y ;
279
284
285
+ /*
286
+ Collect statistics on unique objects.
287
+ */
280
288
object = (CCObject * ) AcquireQuantumMemory (number_objects ,sizeof (* object ));
281
289
if (object == (CCObject * ) NULL )
282
290
{
@@ -288,35 +296,30 @@ static MagickBooleanType MergeConnectedComponents(const Image *image,
288
296
for (i = 0 ; i < (ssize_t ) number_objects ; i ++ )
289
297
{
290
298
object [i ].id = i ;
291
- object [i ].bounding_box .x = (ssize_t ) component_image -> columns ;
292
- object [i ].bounding_box .y = (ssize_t ) component_image -> rows ;
293
- GetPixelInfo (image ,& object [i ].color );
299
+ object [i ].bounding_box .x = (ssize_t ) image -> columns ;
300
+ object [i ].bounding_box .y = (ssize_t ) image -> rows ;
294
301
}
295
302
status = MagickTrue ;
296
303
image_view = AcquireVirtualCacheView (image ,exception );
297
- component_view = AcquireVirtualCacheView (component_image ,exception );
298
304
for (y = 0 ; y < (ssize_t ) image -> rows ; y ++ )
299
305
{
300
306
register const Quantum
301
- * restrict p ,
302
- * restrict q ;
307
+ * restrict p ;
303
308
304
309
register ssize_t
305
310
x ;
306
311
307
312
if (status == MagickFalse )
308
313
continue ;
309
314
p = GetCacheViewVirtualPixels (image_view ,0 ,y ,image -> columns ,1 ,exception );
310
- q = GetCacheViewVirtualPixels (component_view ,0 ,y ,component_image -> columns ,1 ,
311
- exception );
312
- if ((p == (const Quantum * ) NULL ) || (q == (const Quantum * ) NULL ))
315
+ if (p == (const Quantum * ) NULL )
313
316
{
314
317
status = MagickFalse ;
315
318
continue ;
316
319
}
317
320
for (x = 0 ; x < (ssize_t ) image -> columns ; x ++ )
318
321
{
319
- i = (ssize_t ) * q ;
322
+ i = (ssize_t ) * p ;
320
323
if (x < object [i ].bounding_box .x )
321
324
object [i ].bounding_box .x = x ;
322
325
if (x > (ssize_t ) object [i ].bounding_box .width )
@@ -325,55 +328,21 @@ static MagickBooleanType MergeConnectedComponents(const Image *image,
325
328
object [i ].bounding_box .y = y ;
326
329
if (y > (ssize_t ) object [i ].bounding_box .height )
327
330
object [i ].bounding_box .height = (size_t ) y ;
328
- object [i ].color .red += GetPixelRed (image ,p );
329
- object [i ].color .green += GetPixelGreen (image ,p );
330
- object [i ].color .blue += GetPixelBlue (image ,p );
331
- object [i ].color .alpha += GetPixelAlpha (image ,p );
332
- object [i ].color .black += GetPixelBlack (image ,p );
333
- object [i ].centroid .x += x ;
334
- object [i ].centroid .y += y ;
335
- object [i ].area ++ ;
336
331
p += GetPixelChannels (image );
337
- q += GetPixelChannels (component_image );
338
332
}
339
333
}
340
334
for (i = 0 ; i < (ssize_t ) number_objects ; i ++ )
341
335
{
342
336
object [i ].bounding_box .width -= (object [i ].bounding_box .x - 1 );
343
337
object [i ].bounding_box .height -= (object [i ].bounding_box .y - 1 );
344
- object [i ].color .red = (MagickRealType ) (object [i ].color .red /
345
- object [i ].area );
346
- object [i ].color .green = (MagickRealType ) (object [i ].color .green /
347
- object [i ].area );
348
- object [i ].color .blue = (MagickRealType ) (object [i ].color .blue /
349
- object [i ].area );
350
- object [i ].color .alpha = (MagickRealType ) (object [i ].color .alpha /
351
- object [i ].area );
352
- object [i ].color .black = (MagickRealType ) (object [i ].color .black /
353
- object [i ].area );
354
- object [i ].centroid .x = object [i ].centroid .x /object [i ].area ;
355
- object [i ].centroid .y = object [i ].centroid .y /object [i ].area ;
356
338
}
357
- component_view = DestroyCacheView (component_view );
358
- image_view = DestroyCacheView (image_view );
359
- qsort ((void * ) object ,number_objects ,sizeof (* object ),CCObjectCompare );
360
- (void ) fprintf (stdout ,
361
- "Objects (id: bounding-box centroid area mean-color):\n" );
339
+ /*
340
+ Merge objects below area threshold.
341
+ */
362
342
for (i = 0 ; i < (ssize_t ) number_objects ; i ++ )
363
343
{
364
- char
365
- mean_color [MaxTextExtent ];
366
-
367
- if (status == MagickFalse )
368
- break ;
369
- GetColorTuple (& object [i ].color ,MagickFalse ,mean_color );
370
- (void ) fprintf (stdout ,
371
- " %.20g: %.20gx%.20g%+.20g%+.20g %+.1f,%+.1f %.20g %s\n" ,(double )
372
- object [i ].id ,(double ) object [i ].bounding_box .width ,(double )
373
- object [i ].bounding_box .height ,(double ) object [i ].bounding_box .x ,
374
- (double ) object [i ].bounding_box .y ,object [i ].centroid .x ,
375
- object [i ].centroid .y ,(double ) object [i ].area ,mean_color );
376
344
}
345
+ image_view = DestroyCacheView (image_view );
377
346
object = (CCObject * ) RelinquishMagickMemory (object );
378
347
return (status );
379
348
}
@@ -621,11 +590,12 @@ MagickExport Image *ConnectedComponentsImage(const Image *image,
621
590
status = ConnectedComponentsStatistics (image ,component_image ,(size_t ) n ,
622
591
exception );
623
592
artifact = GetImageArtifact (image ,"connected-components:area-threshold" );
593
+ area_threshold = 0.0 ;
624
594
if (artifact != (const char * ) NULL )
625
595
area_threshold = StringToDouble (artifact ,(char * * ) NULL );
626
596
if (area_threshold > 0.0 )
627
- status = MergeConnectedComponents (image , component_image ,(size_t ) n ,
628
- area_threshold , exception );
597
+ status = MergeConnectedComponents (component_image ,(size_t ) n , area_threshold ,
598
+ exception );
629
599
if (status == MagickFalse )
630
600
component_image = DestroyImage (component_image );
631
601
return (component_image );
0 commit comments