Does something like this exist?

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
bluechipps
Posts: 5
Joined: 2018-06-29T19:16:52-07:00
Authentication code: 1152

Does something like this exist?

Post by bluechipps » 2018-06-29T20:31:56-07:00

Hey guys I could really use your help. I have spent so much time searching for a solution that I'm worn out, but before I give up I figure it couldn't hurt to ask here.

So the end result that I'm trying to achieve is... given a standard RGB image, and for each individual pixel, filter/delete/replace it based on how close it is to any shade of pure grey. Another way to say it would be, keep only black, white and pure grey pixels... but allow fuzziness for grey.

An example situation would be like if you were to overlay/merge a 80% opaque grayscale image over a colorful image... then try to cut out the background, aka anything with color, except that now the grey stuff which you want to keep will have slight color variations due to the 80% opacity.

Another example, which is actually what I am trying to do... OCR/extract some 80% opaque white shadowed text from any type of background.

Image

Actually for this specific project, I am able to narrow it down ahead of time to the box around the text, aka can count on the fact that nothing in the background will be brighter/whiter/lighter? than the text i wish to OCR

I'm sorry, I'm guessing there is probably some perfect terminology to easily describe this stuff that I just haven't learned yet :(

User avatar
fmw42
Posts: 24125
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Does something like this exist?

Post by fmw42 » 2018-06-29T21:59:23-07:00

Not sure what you want to do. But if you want to keep only grayish values, then convert to HCL colorspace and take only pixels that have C=0 (no saturation). If you can explain better, that would help. Also always provide your Imagemagick version and platform since syntax may differ.

bluechipps
Posts: 5
Joined: 2018-06-29T19:16:52-07:00
Authentication code: 1152

Re: Does something like this exist?

Post by bluechipps » 2018-06-29T22:06:02-07:00

Thanks I'll take a look at the potential of using the HCL colorspace. Sorry but I'm not sure how to explain any better, described the desired results and gave 2 examples including one of exactly what I am trying to do.

ImageMagick 6.8.9-10 Q16 i686 2018-06-10
Windows 7

User avatar
GeeMack
Posts: 653
Joined: 2015-12-01T22:09:46-07:00
Authentication code: 1151
Location: Central Illinois, USA

Re: Does something like this exist?

Post by GeeMack » 2018-06-29T22:19:09-07:00

bluechipps wrote:
2018-06-29T20:31:56-07:00
Actually for this specific project, I am able to narrow it down ahead of time to the box around the text, aka can count on the fact that nothing in the background will be brighter/whiter/lighter? than the text i wish to OCR
From the Windows command line you can try something like this with your example image...

Code: Select all

convert ss0495.png -crop 200x38+36+9 -threshold 75% output.png
The "-crop" isolates the part with the grayed background. The "-threshold" makes everything above 75% white, and everything below 75% black. The result is an image "output.png" with a black background and the text in white. You can "-negate" that before the output to make it black on white.

To run it from a BAT script be sure to make single percent signs "%" into doubles "%%".

For ImageMagick 7 use "magick" instead of "convert".

bluechipps
Posts: 5
Joined: 2018-06-29T19:16:52-07:00
Authentication code: 1152

Re: Does something like this exist?

Post by bluechipps » 2018-06-29T23:38:07-07:00

Yeah I been messing around with threshold a bunch and its definitely close to what I need. Um is there a way to make the command apply to all 3 channels if any one of them are above/below the threshold? For example, if i were to apply a 50% black threshold to the color (50, 200, 200) it changes it to (0, 200, 200). How could I make it so that if any of the channels are below 50%, then set color to (0, 0, 0)?

Edit: Actually thats not quite right either, I need to keep any colors that are close to any shade of pure grey regardless of how light or dark they are. basically I need to nuke any pixel that is something other than black, white, or very close to grey

User avatar
fmw42
Posts: 24125
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Does something like this exist?

Post by fmw42 » 2018-06-30T10:15:29-07:00

try the following. I separate the Chroma channel and threshold very low to get only low saturation colors (near white, gray, black). Then use that as a mask to put into the alpha channel of the original.

Code: Select all

convert image.png  ^
( -clone 0 -colorspace HCL -channel g -separate +channel -threshold 0.2% -negate +write tmp.png ) ^
-alpha off -compose copy_opacity -composite result.png
It is not too good. But the closest to what you describe that I can think of at the moment. The problem is that there are other regions in your image that have white/gray/black areas.

User avatar
GeeMack
Posts: 653
Joined: 2015-12-01T22:09:46-07:00
Authentication code: 1151
Location: Central Illinois, USA

Re: Does something like this exist?

Post by GeeMack » 2018-06-30T10:44:54-07:00

bluechipps wrote:
2018-06-29T23:38:07-07:00
For example, if i were to apply a 50% black threshold to the color (50, 200, 200) it changes it to (0, 200, 200). How could I make it so that if any of the channels are below 50%, then set color to (0, 0, 0)?
First, you need to describe what you're doing by posting some actual examples of your script, code, or command. The best answers will depend on what series of operations you need and in what order. Without more to go on, you won't likely get such good advice here.

That said, you can obtain all sorts of image data and manipulate almost everything conditionally using FX expressions as described at THIS link. You can use a simple IM command like this to output "0" if the mean of the red channel is less than 50%, or the mean of the green channel is less than 50%, or the mean of the blue channel is less than 50%. It will output "1" otherwise.

Code: Select all

convert input.png -format "%[fx:mean.r<0.5||mean.g<0.5||mean.b<0.5?0:1]" info:
Many, but not all, of these sorts of calculations can be done directly inside the IM command. Using IM version 7 gives you far more options to use inline FX expressions.

bluechipps
Posts: 5
Joined: 2018-06-29T19:16:52-07:00
Authentication code: 1152

Re: Does something like this exist?

Post by bluechipps » 2018-06-30T11:36:49-07:00

Wow no shit... this FX command is crazy! No doubt that this will be all I need. Thanks a ton for kicking me in the right direction

User avatar
fmw42
Posts: 24125
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Does something like this exist?

Post by fmw42 » 2018-06-30T12:12:01-07:00

Note that -fx is rather slow. So if you can do it otherwise, that would be faster. For example if you want all three channels to put values below 50% to black, you can use

Code: Select all

convert input.png -channel rgb -black-threshold 50% result.png
See http://www.imagemagick.org/script/comma ... -threshold

bluechipps
Posts: 5
Joined: 2018-06-29T19:16:52-07:00
Authentication code: 1152

Re: Does something like this exist?

Post by bluechipps » 2018-07-01T01:01:48-07:00

Holy crap guys, after 3 days of research I think I finally got it! Well, I got the formula which produces the result that I wanted it to... So now that I have the result I can decide if its actually what I needed for my project rofl. I think I might put off answering that question til tomorrow so I can at least feel good about everything I've learned for a bit...

Anyway, here's what I came up with. I know I could add more to it to make it pretty and/or more versatile but for now here is just the important parts of it.

Code: Select all

convert test3.png ( -clone 0 -channel RGB ^
		-fx "( abs(p.r-p.g)>0.04 || abs(p.r-p.b)>0.04 || abs(p.b-p.g)>0.04 ) ? 0 : 1" ) ^
		-alpha off -compose copy_opacity -composite result.png
Feels good being able to put it in one line too, thanks to fmw42's example of how to use copy_opacity <3 Oh and another shout out to GeeMack for revealing to me the power of -FX/mathstuffs!

Post Reply