Separating key color and everything else preserving alpha

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
brianleake
Posts: 5
Joined: 2014-06-05T09:40:18-07:00
Authentication code: 6789

Separating key color and everything else preserving alpha

Post by brianleake »

I have a tricky problem I've been struggling with for a few days, hope those who are pros in Image Magick might be able to help me...

I have an RGBA .PNG image consisting of regular image artwork (eg. a sword) and action lines (eg. a swipe) that needs to be separated out as two images. The action lines are always 100% red (1.0,0.0,0.0), but can have any per-pixel alpha value. The source artwork is everything else, and can also have any RGBA value (except the red of course). (Note - we'll probably need to be able pass in which RGB indicate the action lines in future, eg. purple). To be clear, this isn't about separating a color channel (such as R,G,B) but being able to separate a key color into one image, and everything else into a separate image whilst preserving alpha for both.

Here is an example of an image with the red action lines --
https://drive.google.com/file/d/0B9Gh1o ... sp=sharing

The two separate images I'm trying to derive from the source image are --

1. Keep action lines only (100% red, any alpha) - preserve the alpha component of those pixels, and replacing all other colors for transparent white background. Would also be useful to be able to change the red to any other color (preserving the per-pixel alpha) in the process, but that's a secondary concern.
Example (mock-up) output - https://drive.google.com/file/d/0B9Gh1o ... sp=sharing

2. Keep non-action lines only preserving the alpha component of those pixels, and replace the action line (100% red) pixels for transparent white.
Example (mock-up) output - https://drive.google.com/file/d/0B9Gh1o ... sp=sharing

I've tried all manner of -transparent, +transparent, -compose, -alpha on, -alpha off, etc. But really struggling on this one. Would very much appreciate any advice folks can give.

Many thanks,

-- Brian.
Indie developer
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Separating key color and everything else preserving alph

Post by fmw42 »

You did not specify your IM version or platform. Please do so in the future on all posts.

Here is one way in unix syntax that works for this image. I cannot say about other images, because it relies upon the action lines being mid gray in the alpha channel and your knife not have any gray in it in the alpha channel.

Note that the image under the alpha channel has all kinds of color changes. You would be best to make its background consistent, which is what I did with -background white -alpha background, though in this case, this step is probably not really needed. You can see this by separating the alpha channel and its underlying image and looking at them. I do that in the second and third lines in the script

Also I just guessed at 10% for the fuzz, since I did not accurately measure the alpha values for the action lines. You may want to accurately measure the range of values in the alpha channel for the action lines and to choose the optimal fuzz value and the average graylevel to use with the -fuzz rather than just gray.

Basically all I am doing is separating the alpha channel and its underlying image. Then processing the alpha channel to make either the knife or the action lines black so that they do not show up later. The two processed alpha channels are then put back on the underlying image separately, not the original image to make the two new images.

To just separate the two images:

Original:
Image

Code: Select all

convert Original-Both.png -background white -alpha background \
\( -clone 0 -alpha off \) \
\( -clone 0 -alpha extract \) \
\( -clone 2 -fuzz 10% -fill black -opaque gray \) \
\( -clone 1 -clone 3 -alpha off -compose copy_opacity -composite -write original_knife.png \) \
\( -clone 2 -fuzz 10% -fill black +opaque gray \) \
\( -clone 1 -clone 5 -alpha off -compose copy_opacity -composite \) \
-delete 0-5 original_actionlines.png
Image

and

Image


To separate and change the colors of the action lines:

Code: Select all

convert Original-Both.png -background white -alpha background \
\( -clone 0 -alpha off \) \
\( -clone 0 -alpha extract \) \
\( -clone 2 -fuzz 20% -fill black -opaque gray \) \
\( -clone 1 -clone 3 -alpha off -compose copy_opacity -composite -write original_knife.png \) \
\( -clone 2 -fuzz 20% -fill black +opaque gray \) \
\( -clone 1 -fill purple -colorize 100 -clone 5 -alpha off -compose copy_opacity -composite \) \
-delete 0-5 original_actionlines2.png
Image

and

Image

The above can be made more efficient by deleting the temp files as soon as they are not needed and renumbering the clones appropriately.

For Windows syntax:

1) change \( and \) to just ( and )
2) use %% rather than %
3) change line ending \ to ^

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

There may be other ways to do this in IM. This is just one way.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Separating key color and everything else preserving alph

Post by snibgo »

There are many ways to skin a cat. Here's mine. Windows BAT syntax.

1. Turn non-red into transparent white. Also change red to green, just for fun. Remove that line if you don't want it.

Code: Select all

convert ^
  original-both.png ^
  -alpha off +transparent Red -alpha on ^
  -fill Green -opaque Red ^
  -background White -alpha background ^
  o.png

2. Turn red into transparent white. I do this in two stages. The first creates a mask that is black where it was red, and is otherwise black/gray/white representing the original alpha. The second turns red into white, then copies transparency from the mask.

Code: Select all

convert ^
  original-both.png ^
  ( -clone 0 -alpha Extract ) ^
  ( -clone 0 ^
    -alpha off ^
    -fill White +opaque Red ^
    -fill Black -opaque Red ^
  ) ^
  -delete 0 ^
  -compose Multiply -composite ^
  mask.png

convert ^
  original-both.png ^
  -alpha off -fill White -opaque Red -alpha on ^
  mask.png -compose CopyOpacity -composite ^
  w.png
All three converts could be squished into one.
snibgo's IM pages: im.snibgo.com
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Separating key color and everything else preserving alph

Post by snibgo »

CORRECTION: I've just noticed that for task 1, you want to retain the alpha of the red lines. My command above makes them opaque. Sorry. This keeps the alpha. (It also turns red to green, keeping the alpha. Remove the line if you don't want it.)

Code: Select all

convert ^
  original-both.png ^
  -alpha off ^
  -fill Black +opaque Red ^
  -fill White -opaque Red ^
  lineMask.png

convert ^
  original-both.png ^
  -alpha extract ^
  lineMask.png ^
  -compose Multiply -composite ^
  lineMask2.png

convert ^
  original-both.png ^
  -alpha off -fill Green -colorize 100 ^
  lineMask2.png ^
  -compose CopyOpacity -composite ^
  o.png
snibgo's IM pages: im.snibgo.com
brianleake
Posts: 5
Joined: 2014-06-05T09:40:18-07:00
Authentication code: 6789

Re: Separating key color and everything else preserving alph

Post by brianleake »

fmw42 wrote:You did not specify your IM version or platform. Please do so in the future on all posts.

...

Also I just guessed at 10% for the fuzz, since I did not accurately measure the alpha values for the action lines. You may want to accurately measure the range of values in the alpha channel for the action lines and to choose the optimal fuzz value and the average graylevel to use with the -fuzz rather than just gray.
Thank you for taking the time to write this up, very much appreciated. I'm using 6.8.7-7 on Mac OS Mavericks.

So I'm curious why the fuzz factor is needed, is this because there is a range of alpha in the image? I'm concerned this option might not work, as it's entirely possible there could be an alpha range from 0.0 -> 1.0 in the action lines, rather than a narrow range. The value of a "match" for the action lines should purely be based on the RGB, not the alpha. The alpha just needs to be preserved after separation.
brianleake
Posts: 5
Joined: 2014-06-05T09:40:18-07:00
Authentication code: 6789

Re: Separating key color and everything else preserving alph

Post by brianleake »

snibgo wrote:CORRECTION: I've just noticed that for task 1, you want to retain the alpha of the red lines. My command above makes them opaque. Sorry. This keeps the alpha. (It also turns red to green, keeping the alpha. Remove the line if you don't want it.)
Awesome! :-) This seems to do the trick to separate out the red lines and retain the alpha. Please could I also ask if there is a way this technique could be modified to generate the image of the knife without the action lines? (whilst also preserving alpha) - the image no 2. I mentioned in the original question.

BTW, I've uploaded a version of the knife with a little bit of alpha towards the handle --
https://drive.google.com/file/d/0B9Gh1o ... sp=sharing

You guys are really awesome in lending a hand, thanks again!
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: Separating key color and everything else preserving alph

Post by fmw42 »

Then use user snibgo's method. As we both said, often, there are several ways to approach doing things. Pick the one that seems best for your application. You will need to convert snibgo's method to unix syntax.

The fuzz may be needed in his method also, depending upon whether your objects are anti-aliased. I did not take time to look carefully at your alpha channel to check that out.
brianleake
Posts: 5
Joined: 2014-06-05T09:40:18-07:00
Authentication code: 6789

Re: Separating key color and everything else preserving alph

Post by brianleake »

fmw42 wrote:Then use user snibgo's method. As we both said, often, there are several ways to approach doing things. Pick the one that seems best for your application. You will need to convert snibgo's method to unix syntax.

The fuzz may be needed in his method also, depending upon whether your objects are anti-aliased. I did not take time to look carefully at your alpha channel to check that out.
I figured having anti-aliasing in the images is only going to cause problems.
snibgo
Posts: 12159
Joined: 2010-01-23T23:01:33-07:00
Authentication code: 1151
Location: England, UK

Re: Separating key color and everything else preserving alph

Post by snibgo »

brianleake wrote:Please could I also ask if there is a way this technique could be modified to generate the image of the knife without the action lines? (whilst also preserving alpha) - the image no 2. I mentioned in the original question.
See my first post on this thread, under "2." My correction was only for task 1, and I think my original task 2 is what you want. But I may have misunderstand your requirement.

Fred and I have made different assumptions about what defines action lines. I have taken it as "colour red, of any alpha". Fred has (I think) taken it as "middle alpha, of any colour". This would cope with a common situation where anti-aliasing occurs in the colour channels.

The images aren't anti-aliased, but I think anti-aliasing would be okay with my commands, provided action lines are defined as exactly Red (or any other given color.) In other words, I assume there is no anti-aliasing in the colour channels of the action lines.
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: Separating key color and everything else preserving alph

Post by fmw42 »

I put snibgo's method together into one command line in unix syntax with a slight variation.

Here is for #1 red:

Code: Select all

convert Original-Both.png \
\( -clone 0 -alpha off \) \
\( -clone 0 -alpha extract \) \
-delete 0 \
\( -clone 0 -fill white +opaque Red -fill black -opaque Red \) \
\( -clone 1 -clone 2 -compose multiply -composite -clone 0 +swap \
    -compose copy_opacity -composite -write original_knife2.png \) \
\( -clone 2 -negate \) \
-delete 2,3 \
\( -clone 1 -clone 2 -compose multiply -composite -clone 0 +swap \
    -compose copy_opacity -composite \) \
-delete 0-2 \
original_action_lines2a.png

Here is for #2 purple:

Code: Select all

convert Original-Both.png \
\( -clone 0 -alpha off \) \
\( -clone 0 -alpha extract \) \
-delete 0 \
\( -clone 0 -fill white +opaque Red -fill black -opaque Red \) \
\( -clone 1 -clone 2 -compose multiply -composite -clone 0 +swap \
    -compose copy_opacity -composite -write original_knife2.png \) \
\( -clone 2 -negate \) \
-delete 2,3 \
\( -clone 1 -clone 2 -compose multiply -composite \) \
\( -clone 0 -fill purple -colorize 100 -clone 3 -compose copy_opacity -composite \) \
-delete 0-3 \
original_action_lines2b.png
If you want to just use the second method for both cases, you can put purple back to red to get the equivalent of the red only method.

Note that in this approach as well as snibgo's, the underlying image on the action lines will now not contain the knife, but will be solid color.

If you want both backgrounds to be solid color, say either white (or black), then you can do this to make it white.

Code: Select all

convert Original-Both.png -background white \
\( -clone 0 -alpha off \) \
\( -clone 0 -alpha extract \) \
-delete 0 \
\( -clone 0 -fill white +opaque Red -fill black -opaque Red \) \
\( -clone 1 -clone 2 -compose multiply -composite -clone 0 +swap \
    -compose copy_opacity -composite -alpha background -write original_knife2.png \) \
\( -clone 2 -negate \) \
-delete 2,3 \
\( -clone 1 -clone 2 -compose multiply -composite \) \
\( -clone 0 -fill purple -colorize 100 -clone 3 -compose copy_opacity -composite -alpha background \) \
-delete 0-3 \
original_action_lines2b.png
brianleake
Posts: 5
Joined: 2014-06-05T09:40:18-07:00
Authentication code: 6789

Re: Separating key color and everything else preserving alph

Post by brianleake »

You guys absolutely rock! Thank you so much for your assistance throughout the day today. All of these tips have been immensely helpful, I think I have enough to fix up soon pretty cool shell scripts to do what I need.

Again, thank you all! :D
Post Reply