Detecting black along image side edges

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
kirash4
Posts: 34
Joined: 2010-04-12T15:30:59-07:00
Authentication code: 8675308

Detecting black along image side edges

Post by kirash4 »

How can I determine if an image has a vertical black bar on either left or right edge (whether it's 1 pixel wide or 100 pixels wide)? I'm trying to determine if I need to pad an image or not: if there is no edge, then I will pad. If there already is one, then do nothing. I'm working with Magick++ writing in c++.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Detecting black along image side edges

Post by fmw42 »

In command line, you can:

1) crop the left 1px wide edge and the right 1px wide edge of the image and then check the mean value

Code: Select all

convert image[1x+0+0] -format "%[mean]" info:
For the left edge

and similarly

Code: Select all

convert image[1x+WL+0] -format "%[mean]" info:
for the right side, where WL=width-1 (you must precompute that)

If the results are zero, it is a black stripe.

OR

2) scale the image down to one row and check the first and last pixel in the resulting scaled image

Code: Select all

convert image -scale x1! -format "%[pixel:u.p{0,0}]" info:
convert image -scale x1! -format "%[pixel:u.p{w-1,0}]" info:
If the results are "black", it is a black stripe. Note here that using this method, you don't have to precompute the width.

If the edges are not completely black or 0, then either there are non-black pixels or the whole edge is grayscale but close to black.

So what would you want if the edge was gray(1) or graylevel is 1 rather than 0. How close a match is good enough.

If you know that the edge is perfectly black, then the above analysis works fine. But if it is say black with non-black pixel, then you won't get a perfect 0 or "black" for the result.


Sorry I do not know the API equivalent.
kirash4
Posts: 34
Joined: 2010-04-12T15:30:59-07:00
Authentication code: 8675308

Re: Detecting black along image side edges

Post by kirash4 »

What if there is a 10 pixel wide band on either side, or if one side has 20 pixels of black and the other 7 pixels? Do I continue to loop that till I find values that aren't 0? And I'm not sure yet what I'm going to do if instead of pure black, I encounter values that are low enough to be black, but aren't, like RGB(1, 1, 1) ...
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Detecting black along image side edges

Post by snibgo »

Another possibility is to add a black border and find what would be trimmed with "-format %@", with or without a fuzz.
snibgo's IM pages: im.snibgo.com
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Detecting black along image side edges

Post by fmw42 »

kirash4 wrote:What if there is a 10 pixel wide band on either side, or if one side has 20 pixels of black and the other 7 pixels? Do I continue to loop that till I find values that aren't 0? And I'm not sure yet what I'm going to do if instead of pure black, I encounter values that are low enough to be black, but aren't, like RGB(1, 1, 1) ...
I thought you did not care how thick the border was just so long as the left and right columns are black! I thought you were looking to find if the image has any black edge on the left or right vs no black on either side.
kirash4
Posts: 34
Joined: 2010-04-12T15:30:59-07:00
Authentication code: 8675308

Re: Detecting black along image side edges

Post by kirash4 »

fmw42 wrote:
kirash4 wrote:What if there is a 10 pixel wide band on either side, or if one side has 20 pixels of black and the other 7 pixels? Do I continue to loop that till I find values that aren't 0? And I'm not sure yet what I'm going to do if instead of pure black, I encounter values that are low enough to be black, but aren't, like RGB(1, 1, 1) ...
I thought you did not care how thick the border was just so long as the left and right columns are black! I thought you were looking to find if the image has any black edge on the left or right vs no black on either side.
Sorry for the misunderstanding. I do need to find not only whether it has a black edge, but also how much of it. Basically, if there's only a certain amount of black, I will either add more, or none at all. The application here is to figure out how far apart I'm tiling a given image. If there's already a black edge on either or both sides, I need to figure out how big they are. If they're big enough, I'll process as is. But, if they're not, I will be padding it with more.

Another possibility is temporary strip all the black and get the dimensions, then extent it back to final requirements, but that too could be problematic.

It's also entirely possible that I'm making a volcano out of an ant hill here ...
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Detecting black along image side edges

Post by fmw42 »

Another possibility is temporary strip all the black and get the dimensions, then extent it back to final requirements, but that too could be problematic.
That seems like the best approach. I do not see why it would be problematic.


If you really need to find out how much black there is, then scale the image down to one row, then threshold 0 to make it binary. Then convert to txt: format and search from the ends to see where the first white pixel occurs.

convert image -scale x1! -threshold 0 txt:

You will have to collect the txt: data in a string and script to find the first white pixel from each end. So the scripting will depend upon whether you are on unix or windows.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Detecting black along image side edges

Post by snibgo »

If you need to find how many colmns on left or right or both are black, I think the easiest way is:

Code: Select all

F:\web\im>%IM%convert x.png -bordercolor black -border 1 -format "%w %h %@" info:

107 102 80x100+21+1
x.png is (before the border) 105x100, with 80 non-black pixels, starting at x-offset 20. Thus there are 20 black columns on the left and 5 on the right.

Use "-fuzz" if you want.
snibgo's IM pages: im.snibgo.com
kirash4
Posts: 34
Joined: 2010-04-12T15:30:59-07:00
Authentication code: 8675308

Re: Detecting black along image side edges

Post by kirash4 »

fmw42 wrote:
Another possibility is temporary strip all the black and get the dimensions, then extent it back to final requirements, but that too could be problematic.
That seems like the best approach. I do not see why it would be problematic.
The problem would be if the image itself has parts of it that are black and runs along the edge ... I'm not sure, but that's the first thing that popped into my head when I though of that possible approach or removing all black.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Detecting black along image side edges

Post by fmw42 »

user snibgo's solution is best. (very elegant!)

But if you had one black pixel on the left, then after scaling to one row, the end pixel would not be zero or black. The scaling is doing an average of the rows, so if the result is not pure black or zero, it is not all black on the edge. So if you are looking for a complete column of black (or several columns of black), the the scaling will show those columns as pure black pixels in the scaled to one row image. Otherwise, after thresholding all the others will be pure white.
kirash4
Posts: 34
Joined: 2010-04-12T15:30:59-07:00
Authentication code: 8675308

Re: Detecting black along image side edges

Post by kirash4 »

snibgo wrote:If you need to find how many colmns on left or right or both are black, I think the easiest way is:

Code: Select all

F:\web\im>%IM%convert x.png -bordercolor black -border 1 -format "%w %h %@" info:

107 102 80x100+21+1
x.png is (before the border) 105x100, with 80 non-black pixels, starting at x-offset 20. Thus there are 20 black columns on the left and 5 on the right.

Use "-fuzz" if you want.
Great, thanks. I'll have to play with it with the Magick++ API to get the same result ... fingers crossed.
Post Reply