RGB to HSV in numpy

偶尔善良 提交于 2021-01-29 06:44:51

问题


I'm trying to implement RGB to HSV conversion from opencv in pure numpy using formula from here:

def rgb2hsv_opencv(img_rgb):
    img_hsv = cv2.cvtColor(img_rgb, cv2.COLOR_RGB2HSV)
    return img_hsv

def rgb2hsv_np(img_rgb):
    assert img_rgb.dtype == np.float32
    
    height, width, c = img_rgb.shape
    r, g, b = img_rgb[:,:,0], img_rgb[:,:,1], img_rgb[:,:,2]  
    
    t = np.min(img_rgb, axis=-1)
    v = np.max(img_rgb, axis=-1)
    
    s = (v - t) / (v + 1e-6)
    s[v==0] = 0
    
    # v==r
    hr = 60 * (g - b) / (v - t + 1e-6)
    # v==g
    hg = 120 + 60 * (b - r) / (v - t + 1e-6)
    # v==b
    hb = 240 + 60 * (r - g) / (v - t + 1e-6)

    h = np.zeros((height, width), np.float32)
    
    h = h.flatten()
    hr = hr.flatten()
    hg = hg.flatten()
    hb = hb.flatten()
    
    h[(v==r).flatten()] = hr[(v==r).flatten()]
    h[(v==g).flatten()] = hg[(v==g).flatten()]
    h[(v==b).flatten()] = hb[(v==b).flatten()]
    
    h[h<0] += 360
    
    h = h.reshape((height, width))
    
    img_hsv = np.stack([h, s, v], axis=-1)
    
    return img_hsv


img_bgr = cv2.imread('00000.png')

img_rgb = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)

img_rgb = img_rgb / 255.0
img_rgb = img_rgb.astype(np.float32)

img_hsv1 = rgb2hsv_np(img_rgb)
img_hsv2 = rgb2hsv_opencv(img_rgb)

print('max diff:', np.max(np.fabs(img_hsv1 - img_hsv2)))
print('min diff:', np.min(np.fabs(img_hsv1 - img_hsv2)))
print('mean diff:', np.mean(np.fabs(img_hsv1 - img_hsv2)))

But I get big diff:

max diff: 240.0
min diff: 0.0
mean diff: 0.18085355

Do I missing something?

Also maybe it's possible to write numpy code more efficient, for example without flatten?

Also I have hard time finding original C++ code for cvtColor function, as I understand it should be actually function cvCvtColor from C code, but I can't find actual source code with formula.


回答1:


From the fact that the max difference is exactly 240, I'm pretty sure that what's happening is in the case when both or either of v==r, v==g are simultaneously true alongside v==b, which gets executed last.

If you change the order from:

h[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]

To:

h[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]

The max difference may start showing up as 120, because of that added 120 in that equation. So ideally, you would want to execute these three lines in the order b->g->r. The difference should be negligible then (still noticing a max difference of 0.01~, chalking it up to some round off somewhere).

h[(v==b).flatten()] = hb[(v==b).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]
h[(v==r).flatten()] = hr[(v==r).flatten()]


来源:https://stackoverflow.com/questions/63691352/rgb-to-hsv-in-numpy

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!