7

Situation:

You have an image with 1 main color and you need to convert it to another based on a given rgb value.

Problem:

There are a number of different, but similar shades of that color that also need to be converted, which makes a simple 'change-all-(0,0,0)-pixels-to-(0,100,200)' solution worthless.

If anyone can point me in the right direction as far as an algorithm or an image manipulation technique that would make this task more manageable that'd be great.

I've been using PIL to attempt this problem but any general tips would be nice.

edit:

Also, I've used this other SO answer (Changing image hue with Python PIL) to do part of what I'm asking (the hue change), but It doesn't take into consideration the saturation or value

edit: http://dpaste.org/psk5C/ shows using pil to look at the rgb values that I have to work with and the hsv's that go along with some.

Community
  • 1
  • 1
tippenein
  • 189
  • 1
  • 4
  • 11
  • You're saying the entire image consists of variations of this one color? Or are there parts of the image that won't be changing? – Mark Ransom Aug 06 '12 at 16:29
  • The general example would be a small icon. Alpha background, single color, blended on edges. I've had no problems with shades of gray or white so far because their color is mostly controlled by the saturation and value (which I haven't manipulated) so I can change the hue all day and those won't be affected – tippenein Aug 06 '12 at 16:36

1 Answers1

4

Refering to the solution in the linked question: You can adjust the shift_hue() function to adjust hue, saturation and value instead of just hue. That should then allow you to shift all of these parameters just as you like.

Original:

def shift_hue(arr, hout):
    r, g, b, a = np.rollaxis(arr, axis=-1)
    h, s, v = rgb_to_hsv(r, g, b)
    h = hout
    r, g, b = hsv_to_rgb(h, s, v)
    arr = np.dstack((r, g, b, a))
    return arr

Adjusted Version:

def shift_hsv(arr, delta_h, delta_, delta_v):
    r, g, b, a = np.rollaxis(arr, axis=-1)
    h, s, v = rgb_to_hsv(r, g, b)
    h += delta_h
    s += delta_s
    v += delta_v
    r, g, b = hsv_to_rgb(h, s, v)
    arr = np.dstack((r, g, b, a))
    return arr

Assuming you know the base color of your original image and the target color you want, you can easily compute the deltas:

base_h, base_s, base_v = rgb_to_hsv(base_r, base_g, base_b)
target_h, target_s, target_v = rgb_to_hsv(target_r, target_g, target_b)
delta_h, delta_s, delta_v  = target_h - base_h, target_s - base_s, target_v - base_v
Community
  • 1
  • 1
Michael Mauderer
  • 3,777
  • 1
  • 22
  • 49
  • This looks like it would work assuming you can accurately find the deltas based on a given RGB. I'm not so convinced that += will do it. I'm working on getting accurate percentages of difference between RGB values so that the delta arguments here would actually be useful. Unless you can give an example of what you'd use as your delta values? – tippenein Aug 06 '12 at 18:39
  • Do you have a concrete 'base color' and 'target color' (in rgb)? – Michael Mauderer Aug 06 '12 at 18:47
  • The code would have to deal with this. If I have an image that is mostly 0,100,200 and I want to change it to 100,100,50 the code would have to figure out the HSV percent change (I'm thinking) As in, compute the deltas by dividing the hsv's of the original rgb by the new rgb's hsv. ..It gets so confusing typing about this. Code is so much more succinct so I'll work on providing an example of what I mean – tippenein Aug 06 '12 at 18:52
  • I just added what you could do if you do have these colors. Basically the target is what you want and therefore known. The base color could be the average color of the image you have. Depending on the exact requirement. (Or you figure out a color value, that should be used) – Michael Mauderer Aug 06 '12 at 18:54
  • I've accepted your answer because it provides what most people in this situation would need. It's a good overview of this stuff and I'll just add an edit if I figure out the way I'm intending on doing it. Thanks – tippenein Aug 06 '12 at 19:01