OpenCV 'cvtColor' 多次执行时改变颜色和饱和度 (python)
OpenCV 'cvtColor' changes color and saturation when executed multiple times (python)
我正在使用 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
因为图像是 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()
我正在使用 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
因为图像是 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()