Select largest connected nonwhite area
Select largest connected nonwhite area
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 )
Is there anybody who has an idea how to do it?
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 )
Is there anybody who has an idea how to do it?
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Select largest connected nonwhite area
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)
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)
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Select largest connected nonwhite area
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/
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/
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Select largest connected nonwhite area
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:
The output (236x409+143+36) is the required crop.
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:
snibgo's IM pages: im.snibgo.com
Re: Select largest connected nonwhite area
Thanks so much for the fast answer.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:
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
Thanks for that help.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/
I think that I can use this script with the center of the image as starting point.
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Select largest connected nonwhite area
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:
The output (236x409+143+36) is the required crop.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:
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:
- fmw42
- Posts: 25562
- Joined: 2007-07-02T17:14:51-07:00
- Authentication code: 1152
- Location: Sunnyvale, California, USA
Re: Select largest connected nonwhite area
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.
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Select largest connected nonwhite area
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.fmw42 wrote:But I think you can remove two -negates and use mpr to avoid saving files to disk.
snibgo's IM pages: im.snibgo.com
Re: Select largest connected nonwhite area
It is probably not the smartest way of doing it but it works very well: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.
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:");
-
- Posts: 2
- Joined: 2013-09-21T03:26:18-07:00
- Authentication code: 6789
Re: Select largest connected nonwhite area
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.
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.
-
- Posts: 12159
- Joined: 2010-01-23T23:01:33-07:00
- Authentication code: 1151
- Location: England, UK
Re: Select largest connected nonwhite area
Code: Select all
convert in.bmp -fill None -floodfill +0+0 Black out.png
snibgo's IM pages: im.snibgo.com
-
- Posts: 2
- Joined: 2013-09-21T03:26:18-07:00
- Authentication code: 6789
Re: Select largest connected nonwhite area
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!
I'm new to ImageMagick and haven't had much chance to play around, or even read the help pages properly. Thank you nonetheless!