complex color conversion problem

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?".
sssddd
Posts: 14
Joined: 2011-02-15T03:16:59-07:00
Authentication code: 8675308

complex color conversion problem

Post by sssddd »

I have some image with an area of certain color that I want to change to another specific color (specified in rgb color). However, the picture contains more colors and shades. See the picture of the girl in a t-shirt:
Image

I want to change the color of that t-shirt to another specific color, say #49171a. First I need to extract the shirt region as a mask. But the shirt contains many darker areas and the girl's face/body contains lighter areas that are close to shirt color as well. I tried some fuzz factor and can't seem to find a good way to extract just the shirt region. (Doing this in photoshop requires too much manual effort.) Is there a way to do this with IM?

Then, if I have a good mask, then what is the best way to fill in the desired color with the same shades/lights so it looks real? Thanks.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: complex color conversion problem

Post by fmw42 »

If you have a good mask for the shirt, then in the version of the image you want to change the color of the shirt, make it grayscale and then use +level-colors to map from black-white to two shades of the same color your desire to change to. Then use the mask to composite the original with the changed image such that the mask uses the changed image for the shirt and the original image elsewhere

see

http://www.imagemagick.org/Usage/color_ ... vel-colors
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: complex color conversion problem

Post by anthony »

Extracting a mask of the 'pink areas.

I figured the best idea was to extract 'pinks' from form HSL space. A Technique called Chroma Key (also known as Green or Blue Screen.

First attempt...

Code: Select all

  convert shirt.jpg -colorspace HSL -channel Hue -separate +channel shirt_hue.jpg
ImageImageImage

Hmmm two problems... First Pink is near red which is at the division where Hue 'rolls over', but I figured I could use -modulate to adjust the hue away from that 'discontinuity' in the hue. So a 1/3 hue roll (33.3 modulate value), and a color lookup of the pink area gets me the 'pink' hue color of gray64 in the image.

The other problem is the gray background!!!!! Gray is has very little hue, so I need to remove any areas with little to no saturation from my final mask, or I'll be changing things in the background.
This is not needed if I limit changes to hue rolls, which does not effect unsaturated colors. But for completeness I will remove that too...

Code: Select all

   convert shirt.jpg -modulate 100,100,33.3  -colorspace HSL \
               -channel Hue,Saturation -separate +channel \
               \( -clone 0 -background none -fuzz 5% +transparent grey64 \) \
               \( -clone 1 -background none -fuzz 10% -transparent black \) \
               -delete 0,1  -alpha extract  -compose multiply -composite \
               shirt_mask.png
ImageImageImage
that just leaves a number of small isolated 'specks' that can be removed with some morphology

Code: Select all

convert shirt_mask.png -morphology Smooth Square shirt_mask_clean.png
Image

Now you have a mask you can use it to limit (clip) the areas of change when you (somehow) recolor your image. In this case I'll just shift the hues using modulate
http://www.imagemagick.org/Usage/color_mods/#modulate

WARNING: I use a 'clip-mask' in this case... Something I have not done before. However Clip masks are masks of areas that are NOT to change. As such they need to be negated, thus the complication in this example.

Code: Select all

convert shirt_mask_clean.png -negate miff:- | \
   convert shirt.jpg -clip-mask miff:-  -modulate 100,100,25 shirt_blue.jpg
ImageImageImage
Yes there is a slight 'pink' border, and one area of skin that turned blue, (and is squarish due to JPEG noise). The Mask needs a little more work. But it is not bad.

The real problem is that using that is so close to skin color is just asking for trouble! Why do you think people use 'green' and 'blue' screens!

ASIDE: Also I would NOT use JPEG as source or working images. Only use it for your final images only!

The above will be used (with your permission for use of the shirt) in IM Examples, Photos, Chroma Keying.
now online http://www.imagemagick.org/Usage/photos/#chroma_key
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
sssddd
Posts: 14
Joined: 2011-02-15T03:16:59-07:00
Authentication code: 8675308

Re: complex color conversion problem

Post by sssddd »

Thanks very much for the replies! This indeed looks very close.

So my question is, if the shirt was blue or green, would I still need to use HSL channel for separation or can I just extract the blue/green directly since the color is different from skin?

Also, for adjusting colors, what I have done so far was using the shirt region as grayscale image and simply do a "-compose multiply" with the color I want. Note that I need to change to a specific rgb color #49171a. I find it worked ok for that color. See the below picture (the mask is off, but you get the idea).
Image

I've also experimented a little with +level-colors, I used black,#49171a, and I find it producing almost same result, see below. Is it because "multiply" uses the same formula?
Image

But I'm not sure if that is the ideal solution for all colors. For example, if the original shirt was a dark color, turning grayscale will produce a mostly black image. Then if the desired color is light (such as pink), then multiply or +level-colors does not seem to work properly. Since I know the rgb of the color I need to replace (pink in this case), and also the color that I need to replace it with (49171a), is there a formula to convert between two known rgb values while retaining shades? "-modulate" seems what I want, but is there a color code conversion table somewhere to look up values that I need?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: complex color conversion problem

Post by anthony »

sssddd wrote:Thanks very much for the replies! This indeed looks very close.

So my question is, if the shirt was blue or green, would I still need to use HSL channel for separation or can I just extract the blue/green directly since the color is different from skin?
With Blue or green you can use a much larger fuzz factor for the HSL separation of the hue.

You would still do that in the hue channel as in RGB space all colors generally has some BLUE in them.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
sssddd
Posts: 14
Joined: 2011-02-15T03:16:59-07:00
Authentication code: 8675308

Re: complex color conversion problem

Post by sssddd »

Thanks for all the help. Can u please help me understand more of "-modulate" operator? How are the values used/determined? Suppose I want to change a source color HSL(H:0.98,S:0.61,L:0.93) to another color HSL(1.01,0.85,0.20), what is the multiplication value for each channel?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: complex color conversion problem

Post by fmw42 »

Modulate applies PERCENT CHANGES in H,S,L where 100 is no change. So if you want to change the hue from one value to another you need to compute the percent difference relative to 100 and use that. But note that HUE is cyclical, so a change of 100 from 100 (0 or 200) will effectively rotate the hue only 180 degrees rather than 360 degrees.

see http://www.imagemagick.org/Usage/color_mods/#color_mods

You may also prefer to use H,S,B rather than H,S,L as it is more intuitive to work with esp, S and B interaction
sssddd
Posts: 14
Joined: 2011-02-15T03:16:59-07:00
Authentication code: 8675308

Re: complex color conversion problem

Post by sssddd »

Sorry I must be missing something. Value 100 means there is no change, right? So what do you mean by "change of 100" only rotate hue 180 degrees? Wouldn't that be a different color?
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: complex color conversion problem

Post by fmw42 »

If you set H=100, there is no change, but if you change 100 by 100 to H=0 or H=200, you get a 180 rotation of the hue. Think of hue as a circle, every 60 degrees you have red, yellow, green, cyan, blue, magenta. So 180 degree change from red will be cyan. So every color in your image will be rotated 180 degree when you set H=0 or 200, but will be unchanged when you use H=100 in -modulate.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: complex color conversion problem

Post by anthony »

fmw42 wrote:Modulate applies PERCENT CHANGES in H,S,L where 100 is no change. So if you want to change the hue from one value to another you need to compute the percent difference relative to 100 and use that. But note that HUE is cyclical, so a change of 100 from 100 (0 or 200) will effectively rotate the hue only 180 degrees rather than 360 degrees.

see http://www.imagemagick.org/Usage/color_mods/#color_mods

You may also prefer to use H,S,B rather than H,S,L as it is more intuitive to work with esp, S and B interaction
A value of 100 means NO CHANGE. -modulate 100,100,100 is no change.

I don't much like the argument handling of module. For example i would prefer to roll hues in terms of degrees of change. But I am not going to change its current handling, and break every script that uses it!

It is difficult to modulate directly form on color to another. A better method would be to first de-saturate, the image (clip masked of course), using -modulate 100,0. You may like to adjust that '100' value so you get a 'perfect gray' in a spot on the image wher you should get a perfect color match. This image can be saved as a pre-processing step. (you could also do this in an image editor (liek gimp), as part of mask adjusting and save it.

Afterwards you can re-add the appropriate Hue, and Saturation values for the exact color wanted.

This will give you the easiest color control to completely replace one color with another.
You may only then need to adjust luminance for bright/dark, values.

Alternately you can use -tint to tint the mid-tone values of the de-saturated image.
See Midtone Color Tinting
http://www.imagemagick.org/Usage/color_mods/#tint
However I find that tint does not specifically set 'perfect grey' to the color specified. where as a other methods shown below the above link (using a CLUT for duo-tone colors) or DIY Maths, or Overlay/Hardlight Composition, does set perfect grey to the color specified.

Hmmm... I thought I had a full example of de-saturating and re-coloring a image. Perhaps I should do this for the rose image, extracting the 'red' for the mask, in my Photo example. The direct hue of that image shows the 'red hue discontinuity' much more clearly. (remember in hue, red is BOTH black and white!)
Image Image Image Example from IM Examples, Channel Separating...
(Should I or Shouldn't I? That is the Question!)
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: complex color conversion problem

Post by anthony »

You may also like to checkout Fred Weinhaus's script HueMap.
http://www.fmwconcepts.com/imagemagick/huemap/index.php

Which if combined with the extraction of a hue channel histogram, may actually provide you with a better match for the the specific set of hue values that need to be changed.

Basically a CLUT modification on just the hue channel may be all that is needed, in which can there is no need to play around with masks, unless you specifically want to limit the change to that area of 'pink' and not that area of 'pink'. That may simplify the clip-mask being used.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
sssddd
Posts: 14
Joined: 2011-02-15T03:16:59-07:00
Authentication code: 8675308

Re: complex color conversion problem

Post by sssddd »

I think CLUT is a good way to replace colors. However, I understand how to change perfect gray to the color I want, but how do I make the original color into the "perfect gray"? Can clut be used on original image directly (not grayscaled)? I'm reading Fred's huemap, is that just want I wanted? What else is missing?
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: complex color conversion problem

Post by anthony »

Yes I only just seen Fred's Huemap too. Yes I think it will do what you want. As long as those specific hues are not found anywhere else.

I have NOT however checked to see if it handles a Red Hue discontinuity in the source image. The Examples don't seem to map 'reds' to some other color. However if can handle the classing problem of generating a Blue Rose from a Red Rose, then it will handle the discontinuity.


The Hue map could use a slighly different syntax that could be helpful in extracting the exact range of hues you want to shift.

Finding the exact bounds of that range can be tricky though, and posibly involve extracting a Hue Histogram.


As for perfect gray tinting. Basically to de-saturate the image, and adjust its luminance so that the original (unwanted) color becomes a 'perfect gray' You save that image (once only for each source image) and then you can re-color it as you like. You will still need a mask to limit the effects to just teh shirt, but it will provide ways of setting a specific color, without loosing any shadow, shades or highlights.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: complex color conversion problem

Post by fmw42 »

To answer Anthony's question about huemap -- it does handle the wrap around at red. Here is an example using the rose: image

convert rose: rose.png

Image

huemap -h 0,240 -t 30 rose.png rose_red2blue.png

Image
sssddd
Posts: 14
Joined: 2011-02-15T03:16:59-07:00
Authentication code: 8675308

Re: complex color conversion problem

Post by sssddd »

Thanks so much for all the help. Huemap is a nice script, the only problem is that the exact range of hue is hard to determine in my case, and I also do not want to change some other areas of "pink". Thus I still used a mask and went with desaturate and use clut to recolor. Once I figured out how to turn the unwanted color to perfect gray (thanks Anthony!), it is now working great! I created a duotone gradient clut (from black to my color to white), then use this clut to map the desaturated image to my color. The result looks perfect. The only slight drawback is that I have to use photoshop to create mask, as I wanted a perfect mask. But this is good enough for me, and this creates the best result anyway.

Thanks again for both of your help. It's amazing what IM can do... almost like a command-line photoshop. :D
Post Reply