Page 1 of 1

Select largest connected nonwhite area

Posted: 2013-09-18T11:17:04-07:00
by Jörn
Hello,

I would like to use IM (or gimp) in batch mode to process an png file in the following way:

- select the largest nonwhite area
- create an rectangle which contains this area and crop to it
- add a border around (I know how to do this step :-) )

Image
Image
Image

Is there anybody who has an idea how to do it?

Re: Select largest connected nonwhite area

Posted: 2013-09-18T11:29:51-07:00
by fmw42
what platform and what version of IM?

If on unix, you can

1) convert everything that is not white to black and negate (invert) the image so white becomes black and black becomes white. This will create a mask image. (convert image -fuzz XX% -fill black +opaque white -negate result)

2) Use my script, separate, at the link below to get all white areas with their trim canvas size and locations

3) Get the image with the largest white area ( you can test each to compute the white count and find the one with the largest count).
convert image -format "%[fx:mean*w*h]" info:

4) Use that image as a mask with your color image to select only the main large red blocks
convert image mask -compose multiply -composite result

5) trim further if needed (-trim) and add a border (-bordercolor white -border X)

Re: Select largest connected nonwhite area

Posted: 2013-09-18T12:21:39-07:00
by fmw42
If you can identify some point in the largest region, then this will work and is much simpler

coords="260,260"
# first line: read original and create a fully white image the same size
# second line: clone the input and replace everything that is not white with black
# third line: floodfill the large black area with red
# fourth line: replace white with black and red with white and reverse the polarity to create a mask image
# fifth line: composite the original, the white image using the mask, trim and add white border
convert original.png \( -clone 0 -fill white -colorize 100 \) \
\( -clone 0 -fuzz 1% -fill black +opaque white \
-fill red -draw "color $coords floodfill" -alpha off \
-fill black -opaque white -fill white -opaque red -negate \) \
-compose over -composite -trim +repage -bordercolor white -border 10 result.png

If on Windows, replace the line end \ with ^, remove all other \, replace % with %%

See http://www.imagemagick.org/Usage/windows/

Re: Select largest connected nonwhite area

Posted: 2013-09-18T12:49:38-07:00
by snibgo
We can find a point in the largest area with morphology, though it uses an unusual definition of "largest": the area with a pixel furthest from any of its edges. Windows script:

Code: Select all

convert ^
  original2.png ^
  -depth 16 ^
  -fill black +opaque white -negate ^
  -negate -write r0.png -negate ^
  -morphology Distance Euclidean:4 ^
  -auto-level ^
  -threshold 65534 ^
  -write r1.png ^
  -mask r0.png -morphology Dilate:-1 rectangle ^
  +mask ^
  -format %%@ info:
The output (236x409+143+36) is the required crop.

Re: Select largest connected nonwhite area

Posted: 2013-09-18T13:42:09-07:00
by Jörn
snibgo wrote:We can find a point in the largest area with morphology, though it uses an unusual definition of "largest": the area with a pixel furthest from any of its edges. Windows script:
Thanks so much for the fast answer.

I should have told you that I'm using version 6.5.4 on linux. My customer probably uses an even older version :-(
So the "-morphology" doesn't work.

Re: Select largest connected nonwhite area

Posted: 2013-09-18T13:51:23-07:00
by Jörn
fmw42 wrote:If you can identify some point in the largest region, then this will work and is much simpler

coords="260,260"
# first line: read original and create a fully white image the same size
# second line: clone the input and replace everything that is not white with black
# third line: floodfill the large black area with red
# fourth line: replace white with black and red with white and reverse the polarity to create a mask image
# fifth line: composite the original, the white image using the mask, trim and add white border
convert original.png \( -clone 0 -fill white -colorize 100 \) \
\( -clone 0 -fuzz 1% -fill black +opaque white \
-fill red -draw "color $coords floodfill" -alpha off \
-fill black -opaque white -fill white -opaque red -negate \) \
-compose over -composite -trim +repage -bordercolor white -border 10 result.png

If on Windows, replace the line end \ with ^, remove all other \, replace % with %%

See http://www.imagemagick.org/Usage/windows/
Thanks for that help.
I think that I can use this script with the center of the image as starting point.

Re: Select largest connected nonwhite area

Posted: 2013-09-18T13:55:48-07:00
by fmw42
snibgo wrote:We can find a point in the largest area with morphology, though it uses an unusual definition of "largest": the area with a pixel furthest from any of its edges. Windows script:

Code: Select all

convert ^
  original2.png ^
  -depth 16 ^
  -fill black +opaque white -negate ^
  -negate -write r0.png -negate ^
  -morphology Distance Euclidean:4 ^
  -auto-level ^
  -threshold 65534 ^
  -write r1.png ^
  -mask r0.png -morphology Dilate:-1 rectangle ^
  +mask ^
  -format %%@ info:
The output (236x409+143+36) is the required crop.


Very clever.

But I think you can remove two -negates and use mpr to avoid saving files to disk. This seems to work for me (in unix notation). However, it is automated, but takes some time to do the dilate:-1


convert \
original.png \
-depth 16 \
-fill black +opaque white -write show: \
-write mpr:mask -negate -write show: \
-morphology Distance Euclidean:4 \
-auto-level -write show: \
-threshold 65534 -write show: \
-mask mpr:mask -morphology Dilate:-1 rectangle \
+mask -write show: \
-format "%@" info:

Re: Select largest connected nonwhite area

Posted: 2013-09-18T14:00:00-07:00
by fmw42
Jörn wrote:
Thanks for that help.
I think that I can use this script with the center of the image as starting point.

You can test if the center is not white. If it is search some number of pixels up, down, left, and right. You can iterate the distance until you find a non-white point near the center.

Another way is to make the mask, then average the image down to 1 row and again from the mask down to one column. You can then find some pixel near the middle of the longest white areas that overlaps in both the row and column image.

Re: Select largest connected nonwhite area

Posted: 2013-09-18T16:32:42-07:00
by snibgo
fmw42 wrote:But I think you can remove two -negates and use mpr to avoid saving files to disk.
True. My script contained "-negate -negate", which is about as pointless as possible. And I remember thinking "I'll use mpr when I've got it working", but never got around to it.

Re: Select largest connected nonwhite area

Posted: 2013-09-19T07:10:01-07:00
by Jörn
fmw42 wrote: You can test if the center is not white. If it is search some number of pixels up, down, left, and right. You can iterate the distance until you find a non-white point near the center.
It is probably not the smartest way of doing it but it works very well:

Code: Select all

#!/usr/bin/perl

my $file = "original.png";

my ($size_x, $size_y, $x_offset, $y_offset) = (`identify $file` =~ /.*?([\d]+)x([\d]+)\+([\d]+)\+([\d]+)/);

my ($point, $offset);

for (my $i = 0.3;$i <= 0.7; $i += 0.1) {

  $point  = sprintf ("%d,%d" , $size_x*$i , $size_y*$i);
  $offset = sprintf ("%d+%d" , $size_x*$i , $size_y*$i);
 
  my $color = `convert ${file}[1x1+$offset] -format "%[fx:floor(255*u.r)],%[fx:floor(255*u.g)],%[fx:floor(255*u.b)]" info:`;
  my ($r, $g, $b) = ($color =~ /([\d]+),([\d]+),([\d]+)/);

  print "Point = $point und $i\n";
  print "RGB = $r $g $b\n";

  last if ($r < 255 or $g < 255 or $b < 255);

}

system("convert $file \\
        -trim +repage \\
        \\( -clone 0 -fill white -colorize 100 \\) \\
        \\( -clone 0 -fuzz 1% -fill black +opaque white \\
        -fill red -draw \"color $point floodfill\" -alpha off \\
        -fill black -opaque white -fill white -opaque red -negate \\) \\
        -compose over -composite -trim +repage \\
        -bordercolor white -border 25 x:");

Re: Select largest connected nonwhite area

Posted: 2013-09-21T03:34:07-07:00
by Haxton Fale
Hello,
I hope you don't mind if I join in, since I have a very similar problem - I need to get rid of the largest black area and replace it with 100% transparency, and I know the (0,0) pixel belongs to it. I know I should extrapolate the correct script/command (I need this on Windows CLI) from your replies, but I don't really have the time for that (sorry!) and I'd really appreciate it if someone helped me write it!
As an added bonus, my input is in BMP and the output is in PNG :) so filenames (sans extensions) can overlap.

Re: Select largest connected nonwhite area

Posted: 2013-09-21T05:10:56-07:00
by snibgo

Code: Select all

convert in.bmp -fill None -floodfill +0+0 Black out.png

Re: Select largest connected nonwhite area

Posted: 2013-09-21T07:15:44-07:00
by Haxton Fale
Yes, that's it, thank you very much!
I'm new to ImageMagick and haven't had much chance to play around, or even read the help pages properly. Thank you nonetheless!