Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

matplotlib colors rgb_to_hsv not working right . Maybe need to report it?

I understand that an RGB to HSV conversion should take RGB values 0-255 and convert to HSV values [0-360, 0-1, 0-1]. For example see this converter in java:

When I run matplotlib.colors.rbg_to_hsv on an image, it seems to output values [0-1, 0-1, 0-360] instead. However, I have used this function on an image like this, and it seems to be working in the right order [H,S,V], just the V is too large.

Example:

In [1]: import matplotlib.pyplot as plt

In [2]: import matplotlib.colors as colors

In [3]: image = plt.imread("/path/to/rgb/jpg/image")

In [4]: print image
[[[126  91 111]
  [123  85 106]
  [123  85 106]
  ..., 

In [5]: print colors.rgb_to_hsv(image)
[[[  0   0 126]
  [  0   0 123]
  [  0   0 123]
  ..., 

Those are not 0s, they're some number between 0 and 1.

Here is the definition from matplotlib.colors.rgb_to_hsv

def rgb_to_hsv(arr):
    """
    convert rgb values in a numpy array to hsv values
    input and output arrays should have shape (M,N,3)
    """
    out = np.zeros(arr.shape, dtype=np.float)
    arr_max = arr.max(-1)
    ipos = arr_max > 0
    delta = arr.ptp(-1)
    s = np.zeros_like(delta)
    s[ipos] = delta[ipos] / arr_max[ipos]
    ipos = delta > 0
    # red is max
    idx = (arr[:, :, 0] == arr_max) & ipos
    out[idx, 0] = (arr[idx, 1] - arr[idx, 2]) / delta[idx]
    # green is max
    idx = (arr[:, :, 1] == arr_max) & ipos
    out[idx, 0] = 2. + (arr[idx, 2] - arr[idx, 0]) / delta[idx]
    # blue is max
    idx = (arr[:, :, 2] == arr_max) & ipos
    out[idx, 0] = 4. + (arr[idx, 0] - arr[idx, 1]) / delta[idx]
    out[:, :, 0] = (out[:, :, 0] / 6.0) % 1.0
    out[:, :, 1] = s
    out[:, :, 2] = arr_max
    return out

I would use one of the other rgb_to_hsv conversions like colorsys, but this is the only vectorized python one I have found. Can we figure this out? Do we need to report it on github?

Matplotlib 1.2.0 , numpy 1.6.1 , Python 2.7 , Mac OS X 10.8

like image 344
chimpsarehungry Avatar asked Jun 27 '13 17:06

chimpsarehungry


1 Answers

It works beautifully if, instead of unsigned int RGB values from 0 to 255, you feed it float RGB values from 0 to 1. It would be nice if the documentation specified this, or if the function tried to catch what seems to be a very likely human error. But you can get what you want simply by calling:

print colors.rgb_to_hsv(image / 255)
like image 99
Jaime Avatar answered Oct 16 '22 06:10

Jaime