问题描述
这是转换rgb-> hsv-> rgb的一些测试:
def rgb2hsv_opencv(img_rgb):
img_hsv = cv2.cvtColor(img_rgb,cv2.COLOR_RGB2HSV)
return img_hsv
def hsv2rgb_opencv(img_hsv):
img_rgb = cv2.cvtColor(img_hsv,cv2.COLOR_HSV2RGB)
return img_rgb
img_bgr = cv2.imread('00000.png')
img_rgb = cv2.cvtColor(img_bgr,cv2.COLOR_BGR2RGB)
img_hsv = rgb2hsv_opencv(img_rgb)
img_rgb2 = hsv2rgb_opencv(img_hsv)
cv2.imwrite('debug_1.png',img_rgb)
cv2.imwrite('debug_2.png',img_rgb2)
print('diff:',np.max(np.fabs(img_rgb - img_rgb2)))
图像看起来一样,但是由于某种原因diff
不为零,是预期的吗?
解决方法
实际上documentation对此主题有一些注释:
如果您将cvtColor与8位图像一起使用,则转换将有一些 信息丢失。对于许多应用程序,这不会引起注意 但建议在需要的应用程序中使用32位图像 完整的颜色范围或在进行操作之前可以转换图像 然后转换回来。
因此,在使用非线性转换之前添加img_rgb = img_rgb.astype(np.float32)
会有所帮助,它将最大吸收差减小到diff: 0.00011444092
并添加img_rgb = img_rgb / 255.0
会带来更多帮助,它将最大绝对吸收值降低到diff: 4.172325e-07
对于HSV,色相范围为[0,179],饱和度范围为[0,255],值范围为[0,255]。不同的软件使用不同的比例。因此,如果将OpenCV值与它们进行比较,则需要将这些范围标准化。 [source]
因此,如果将RGB(256 ^ 3)转换为HSV(180x256x256)并向后转换,则无法获得相同的色彩分辨率,原因很简单,原因是色彩分辨率只有转换到HSV之前的一半。