【问题标题】:RGB to HSV in numpynumpy中的RGB到HSV
【发布时间】:2020-09-01 16:02:06
【问题描述】:

我正在尝试使用 here 中的公式在纯 numpy 中实现从 opencv 到 HSV 的 RGB 转换:

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)))

但我有很大的不同:

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

我错过了什么吗?

还有可能编写更高效的 numpy 代码,例如没有flatten

我也很难找到 cvtColor 函数的原始 C++ 代码,据我了解,它实际上应该是来自 C 代码的函数 cvCvtColor,但我找不到带有公式的实际源代码。

【问题讨论】:

  • 您能否检查并向我们报告哪种颜色的差异最大?也许这只是一个归一化问题(黑白:仅 V 重要:其他值无关紧要)。

标签: numpy opencv rgb hsv


【解决方案1】:

从最大差异正好是 240 的事实来看,我很确定正在发生的情况是 v==rv==gv==b 同时或其中之一同时为真,最后执行.

如果您从以下位置更改订单:

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[(v==r).flatten()] = hr[(v==r).flatten()]
h[(v==b).flatten()] = hb[(v==b).flatten()]
h[(v==g).flatten()] = hg[(v==g).flatten()]

最大差异可能开始显示为 120,因为在该等式中添加了 120。所以理想情况下,你会希望按照 b->g->r 的顺序执行这三行。那么差异应该可以忽略不计(仍然注意到最大差异为 0.01~,将其归结为某处的某个舍入)。

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

【讨论】:

  • 是的,订单 BGR 有助于将最大 abs diff 降低到 0.013458252,但 diff 仍然太高而不能忽略它。
  • 嗯,删除 img_rgb = img_rgb / 255.0 有助于将最大 abs diff 减少到 6.1035156e-05
  • 我不确定,但我认为这种轻微的偏差可能是由于为避免 div by zero 错误而添加的 1e-6s 造成的。也许将划分过程分解为:s=v-ts[v!=0] = s[v!=0] / v[v!=0]s[v==0]=0
猜你喜欢
  • 2012-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多