moys
moys

Reputation: 8033

Change a particular range of colors to anothe color in CV2 or PIL

I have an image as below

In this image, I want to convert yellow numbers to BLACK color & RED regions to gray. The already black & gray regions should not be changed. How to I do that? Can anyone help? I looked at several questions but i am not able to figure it out. Also, since the both yellow & red colors are not exactly the same but are in a range, i cannot to a direct replacement of the colors. CV2 or PIL, both are OK.

If HSV values have to be used, please let me know how to figure the range. This questions has been asked & some answers are already there but I am not able to grasp them, so any additional guidance will be helpful

enter image description here

The output I am expecting is something like the pic below (created by painting the pixels in Gimp). Not exactly what you see, but you get the idea what I am looking for.

enter image description here

Update The solution that I ended up using is as below. This made all the yellow letters as black & that was sufficient for me (i think,with the similar approach all the red areas could be made grey too)

img = Image.open('Testpic.jpg').convert('RGB')

roi = img.crop((652,125,697,295))
orig_color1 = (210,140,0)
orig_color2 = (210,210,210)

replacement_color = (4,4,4)
roi = roi.resize((288, 1014), Image.ANTIALIAS)
data = np.array(roi)
data[((data >= orig_color2)).all(axis = -1)] = (255,0,0)
data[((data >= orig_color1)).all(axis = -1)] = replacement_color
data[((data == (255,0,0))).all(axis = -1)] = (255,255,255)

img2 = Image.fromarray(data, mode='RGB')

Upvotes: 1

Views: 594

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207425

Your image is not the best quality and your results should improve if you can get a better input. I am just showing a technique with ImageMagick and may translate it into Python wand later if anyone likes it - it shouldn't be too hard.

So, rather than selecting ranges in HSL colourspace, in this instance it is easier and probably better to remap the image to a specific palette since you only want to differentiate 4 colours. So, I made the following palette of 4 colours - a black, a grey, a yellow and a red like this:

magick xc:"gray(15)"  xc:"gray(178)" xc:"rgb(230,50,30)" xc:"rgb(230,190,90)"  +append palette.png

That makes this (much enlarged) 4x1 palette:

enter image description here

Then I remapped your image to the colours of that palette:

magick column.png +dither -remap palette.png intermediate.png

enter image description here

Then I replace all colours vaguely close to yellow with black, and all colours vaguely close to red with white:

magick intermediate.png -fill black -fuzz 30% -opaque yellow -fill white -opaque red result.png

enter image description here

Obviously change the -fill white to -fill "gray(180)" if you want the background uniform, or add-threshold 50%`:

enter image description here


If you don't want to use wand for some reason, you can use my answer here to quantise to that specific 4-colour palette just the same.

Upvotes: 2

Related Questions