【问题标题】:OpenCV 'cvtColor' changes color and saturation when executed multiple times (python)OpenCV 'cvtColor' 多次执行时会改变颜色和饱和度(python)
【发布时间】:2021-08-31 04:47:31
【问题描述】:

我正在使用 OpenCV 的函数 cv2.cvtColor 逐步修改图像:

  • 我将原始 BGR 图像转换为 HSV 颜色格式。
  • 我对 HSV 图像进行了一些计算。
  • 我将 HSV 图像转换回 BGR 颜色格式。

最终,BGR 到 HSV 和 HSV 到 BGR 的转换不是完全对偶的,一些(随机)像素会看到其 H 值和 S 值的变化。

我的意思是:

import cv2
import numpy as np


# Load image
original_img = cv2.imread('img.png')
img = original_img.copy()


# Convert image multiple times
for ii in range(50):
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)

    print(f'\niter {ii+1}')
    print(f'H sum: {np.sum(img_hsv[:,:,0])}')
    print(f'S sum: {np.sum(img_hsv[:,:,1])}')
    print(f'V sum: {np.sum(img_hsv[:,:,2])}')


# Display images (resize for convenience)
cv2.imshow('original', cv2.resize(original_img, tuple([s*3 for s in img.shape[:2]])))
cv2.imshow('converted', cv2.resize(img, tuple([s*3 for s in img.shape[:2]])))

cv2.waitKey(0)
cv2.destroyAllWindows()

原始(左)与转换后(右):

您可能会注意到,有一堆像素变红并且饱和度增加。此外,H 和 S 通道变化为(值的总和):

iter 1
H sum: 862253
S sum: 1470471
V sum: 1028930

iter 2
H sum: 847617
S sum: 1511497
V sum: 1028930

...

iter 49
H sum: 796974
S sum: 1570406
V sum: 1028930

iter 50
H sum: 796974
S sum: 1570412
V sum: 1028930

Python 3.8.3 | OpenCV 4.5.1

【问题讨论】:

    标签: python image opencv image-processing hsv


    【解决方案1】:

    因为图像是 8 位的,所以每次迭代都会丢失数据。 见convertion between HSV and RGB。 例如,饱和度是最大分量上的色度(最大值 - 最小值)。 当它转换为 HSV 时,饱和度值将在 0 到 255 之间量化。 附带说明一下,OpenCV 中的最大色调值为 180。

    不使用uchar,而是使用浮点图像执行转换可以防止丢失。我用.astype(np.float32) 更改了你的代码,每次迭代的结果都是一样的。

    H sum: 1739456.625
    S sum: 5764.1796875
    V sum: 1028930.0
    

    修改后的代码:

    import cv2
    import numpy as np
    
    
    # Load image
    original_img = cv2.imread('img.png').astype(np.float32)
    img = original_img.copy()
    
    
    # Convert image multiple times
    for ii in range(50):
        img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
    
        print(f'\niter {ii+1}')
        print(f'H sum: {np.sum(img_hsv[:,:,0])}')
        print(f'S sum: {np.sum(img_hsv[:,:,1])}')
        print(f'V sum: {np.sum(img_hsv[:,:,2])}')
    
    
    # Display images (resize for convenience)
    cv2.imshow('original', cv2.resize(original_img, tuple([s*3 for s in img.shape[:2]])).astype(np.uint8))
    cv2.imshow('converted', cv2.resize(img, tuple([s*3 for s in img.shape[:2]])).astype(np.uint8))
    
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    【讨论】:

    • 谢谢@Burak。尽管它解决了我介绍的原始问题,但您的解决方案也会导致奇怪的行为。不幸的是,我无法从我对图像进行的特定计算中复制它。短篇小说是我用矩阵图像到达最终转换(HSV 到 BGR)。如果它是uint8 转换是好的,如果它是float32,虽然完全等于它的uint8 双胞胎,我在输出图像中得到随机负值。在 BGR 中,max val 为 +255,min val 为 -32.500,mean val 为 -4480。回到uint8 时,我的大部分像素都完全乱了套。
    • @ALai 我不能说我完全理解你的意思,但这个问题可能与 float-uint cast 有关。你确定浮点格式有负值吗?如果没有,请尝试在转换之前使用round 函数。
    • 是的,我确定有负值,因为我直接查看了图像矩阵。正如我告诉你的那样,我无法从我正在做的特定计算中复制这个问题,甚至重复我在我的应用程序中所做的相同的细化步骤,这真的很奇怪。
    猜你喜欢
    • 2016-09-11
    • 1970-01-01
    • 1970-01-01
    • 2020-10-29
    • 2011-05-17
    • 2016-09-25
    • 2011-07-22
    • 2011-01-23
    • 1970-01-01
    相关资源
    最近更新 更多