ujwala patil
ujwala patil

Reputation: 49

ImageMagick Unable to change colour in shade explicitly for image

I want to use ImageMagick to change colour in shade.

I am able to manage the shade change using :

convert input.png  -colorspace HCL -channel R  -evaluate set 5%  +channel -colorspace sRGB output.png 

Using set XX% i am able to get different colours like, red, green, yellow, blue, pink, sky-blue, gray, etc.

The below command works for targeting blue colour :

convert input.png  -colorspace HCL -channel R -separate +channel -level 48,52% output.png 

But I am unable to target other colour explicitly.

For example, if I want to change green colour with some other colour, resulted image will effect green, yellow,red and sky-blue as well.

Is there a way to explicitly change a single colour in shade for :

I tried changing all -channel : R,G,B,C,M,Y,K,A,O.

Using -separate option I can target RBG, but the problem with RGB is R effect red, yellow and pink, G effect green, sky-blue and yellow and B effect blue, pink and Sky-blue.

sample for output : RGB image colour change

expected output : In the above output for "output-0" it effect red,yellow and pink. i want the command which will effect only red. similarly for other colours as well.

links I used : https://www.imagemagick.org/discourse-server/viewtopic.php?t=33361

I am using python to run this command. I am also open to use other libraries which will work with all the colours explicitly.

Upvotes: 3

Views: 630

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207365

If your image is representative like I requested, it is as simple as this:

enter image description here

magick rgb.png -fill white -opaque red result.png

enter image description here

If you also want to affect hues "close to red", you can apply some fuzz:

magick rgb.png -fuzz 40% -fill white -opaque red result.png

enter image description here

Notice that also affects the edges of the red circle where it is a "feathered red".


If not, your ImageMagick code is essentially doing a "Hue rotation" and, as you have noticed, it affects the entire image. Read the Wikipedia page on HSV before continuing. Here is an HSI Hue wheel for reference:

enter image description here

The solution is to do your Hue rotation, but apply its effects via a mask that only selects the colours/areas you want affected. Remember that OpenCV halves the Hue from the range 0..360 to 0..180 so that it can store a Hue in a np.uint8.

So, if we load the same image as above and select only the greens (where Hue is near 120) we can rotate just those into blues by adding 60 (Hue=240):

#!/usr/local/bin/python3
import cv2 as cv
import numpy as np

# Load the image and convert to HSV colourspace
image = cv.imread("rgb.png")

# Convert to HSV and split channels
hsv=cv.cvtColor(image,cv.COLOR_BGR2HSV)
H,S,V = cv.split(hsv)

# Shift only greens (Hue near 120) around hue circle by 120 degrees to blues - remembering OpenCV halves all these values - see comment
H[(H>55)&(H<65)] += 60

# Recombine into single 3-channel image and convert back to RGB
result = cv.merge((H,S,V))
result = cv.cvtColor(result,cv.COLOR_HSV2BGR)

cv.imwrite("result.png",result)

enter image description here


If you want to change the blues (Hue=240) into yellows (Hue=60), just change this:

H[(H>55)&(H<65)] += 60

into this:

H[(H>115)&(H<125)] -= 90

enter image description here


If you want to broaden the range of greens affected, decrease the 55 in my code and/or increase the 65. If you want to move greens to a different hue, either increase or decrease the 60.

You can do all the stuff above with PIL/Pillow if you want to - you don't need to install the (massive) OpenCV.

Keywords: Image, image processing, Python, OpenCV, ImageMagick, Hue, HSL, HSV, hue rotation, colour replacement, selective colour, mask.

Upvotes: 2

Related Questions