How do I use a colour to mask out pixels?

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
dgpeters
Posts: 18
Joined: 2013-09-10T15:47:00-07:00
Authentication code: 6789

How do I use a colour to mask out pixels?

Post by dgpeters »

I want to mask out (ie, blacken) any pixels that have any blue in them. This is not the same thing as removing blue pixels. I've tested dozens of commands but can't achieve that yet. I've spent hours in the documentation and searching with Google.

Actually that's how I'm trying to solve my problem. My real problem, and perhaps there's a more direct solution, is that I want yellow pixels to be white and anything that isn't yellow to be black. But I realize yellow is Red + Green (two channels). So the idea of using blue as a mask is how I think I might achieve that, but perhaps that's the wrong way. If there is a more direct way to isolate the yellow that would be better. By yellow I define that to mean the Red channel >90% and the Green channel is also >90%.

Thanks in advance.

$ convert -version
Version: ImageMagick 7.0.7-15 Q16 x86_64 2017-12-14 http://www.imagemagick.org
Copyright: © 1999-2018 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI
Delegates (built-in): bzlib freetype jng jpeg lcms png raw tiff webp xml zlib
dgpeters
Posts: 18
Joined: 2013-09-10T15:47:00-07:00
Authentication code: 6789

Re: How do I use a colour to mask out pixels?

Post by dgpeters »

Oh, and yellow must also have Blue <5%. I forgot that.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How do I use a colour to mask out pixels?

Post by snibgo »

dgpeters wrote:I want yellow pixels to be white and anything that isn't yellow to be black.
A common way is (Windows BAT syntax):

Code: Select all

magick ^
  in.png ^
  -fuzz 10%% ^
  -fill black +opaque Yellow ^
  -fuzz 0 ^
  -fill White +opaque Black ^
  out.png
This turns everything that isn't yellow into black, and then all not-black is turned white. The first fuzz includes as "yellow" any pixels within 10% of that colour. The second fuzz restores the default setting of fuzz zero, so only pixels that are exactly black remain black.
dgpeters wrote:By yellow I define that to mean the Red channel >90% and the Green channel is also >90%.
And, I assume, the Blue channel can be anything?

I would do that as a colour separation:

Code: Select all

magick ^
  in.png ^
  -channel RG -separate +channel ^
  -threshold 90%% ^
  -compose Darken -composite ^
  out.png
"-channel RG -separate +channel" makes two greyscale images from just the R and G channels. "-threshold" operates on both those images. Then we combine them, takes the darkest of each.

The result is white where input red > 90% and green > 90%, otherwise it is black.

... And then you snuck in the blue requirement, ha! We can threshold the blue channel at 5%, then negate is so the result is white only where B < 5%. Then it gets a bit complicated.

Code: Select all

magick ^
  in.png ^
  ( -clone 0 ^
    -channel RG -separate +channel ^
    -threshold 90%% ^
  ) ^
  ( -clone 0 ^
    -channel B -separate +channel ^
    -threshold 5%% ^
    -negate ^
  ) ^
  -background None ^
  -compose Darken -layers Merge ^
  out.png
snibgo's IM pages: im.snibgo.com
dgpeters
Posts: 18
Joined: 2013-09-10T15:47:00-07:00
Authentication code: 6789

Re: How do I use a colour to mask out pixels?

Post by dgpeters »

Here's how I translated that for macOS:
magick qq.tiff \( -clone 0 -channel RG -separate +channel -threshold 90% \) \( -clone 0 -channel B -separate +channel -threshold 5% -negate \) -background None -compose Darken -layers Merge qq2.tiff
I was getting all black output, but I trusted you, so I played with the percentages until it started to work. Here's what gave me fairly good preliminary results:
magick qq.tiff \( -clone 0 -channel RG -separate +channel -threshold 40% \) \( -clone 0 -channel B -separate +channel -threshold 55% -negate \) -background None -compose Darken -layers Merge qq2.tiff
I will have to study these results and do some more tinkering with the percentages. It's not bad. I hope someone considers making this into a parameter for ImageMagick, something like this: (this would blacken all pixels when the Y channel is below 90%.)
magick qq.tiff -channel Y -maskout 90%
dgpeters
Posts: 18
Joined: 2013-09-10T15:47:00-07:00
Authentication code: 6789

Re: How do I use a colour to mask out pixels?

Post by dgpeters »

I just realized my proposed ImageMagick parameter doesn't do exactly what I want, but you get the idea.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: How do I use a colour to mask out pixels?

Post by snibgo »

"channel Y" already has a meaning, as a channel of CMY or CMYK images. Using this channel might give the effect you want.
snibgo's IM pages: im.snibgo.com
Post Reply