Reputation: 49
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
Reputation: 207365
If your image is representative like I requested, it is as simple as this:
magick rgb.png -fill white -opaque red result.png
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
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:
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)
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
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