python - 为什么从 RGB 到 HSV 的颜色转换会产生损坏的图像?

标签 python opencv matplotlib

我正在努力过滤掉某些颜色的图像,但在使用 hsv/hsl 颜色空间时被卡住了。如果我尝试使用 cv2.Color(image, cv2.COLOR_RGB2HSV) 将使用 matplotlib 读取的图像转换为 HSV生成的图像像这样弄乱了颜色:
Image

据我了解,图像应该像原始图像一样显示
image .

这是正确的还是错误在于我对色彩空间的有限理解?

我还尝试使用 opencv 读取图像,然后将 BGR 转换为 HSV,这带来了不同但仍然有缺陷的图像。我还使用 image = (image * 255).round().astype(np.uint8) 将图像转换为 uint8 ,仍然没有工作

import matplotlib.image as mpimg
import matplotlib.pyplot as plt
import cv2
import numpy as np
image = mpimg.imread("Screenshots/vlcsnap-2019-07-22-08h42m14s251.png")
hsv = cv2.cvtColor(image, cv2.COLOR_RGB2HSV)
hls = cv2.cvtColor(image, cv2.COLOR_RGB2HLS)
plt.figure()
plt.imshow(hls)
plt.figure()
plt.imshow(hsv)

除了我在运行代码时还会收到以下警告:
“使用 RGB 数据将输入数据剪切到 imshow 的有效范围(浮点数为 [0..1] 或整数为 [0..255])。”

最佳答案

色调 (H) channel 是一个连续色环的重要后果是,在可视化 HSV 转换时应牢记这一点。这种 block 状是不可避免的,即使由于没有将 0-360 H channel 重新缩放为 0.0-1.0 以使用 matplotlib 绘制为 float32 而修复剪辑也是如此。

与饱和度 (S) 和值 (V) channel 的线性比例不同,H channel 的最小值和最大值实际上是色环上红色的相邻值。由于 0 到 255 或 1.0 之间的急剧过渡,在原始图像中实际上同样偏红的部分,您经常会在任何代表 H 的 channel 中看到粗糙的 block 状区域。

您实际上并没有发布您的原始图像,但看起来像是 matplotlib 图的屏幕截图,所以我无法准确地重现您的效果。但是,要查看效果,请仅使用原始 H channel 查看 H channel ,我想您会明白我的意思:

H, S, V = cv2.split(hsv)
# here's the opencv way to see it
cv2.imshow('H', H)
cv2.waitKey(0)

请注意非常亮和非常暗区域彼此相邻的 block 状过渡,即使原始图像中存在平滑的红色变化。

您正在使用 matplotlib,它需要 RGB 图像。所以色调显示为红色,饱和度显示为绿色,值显示为蓝色。在您看到那些非红色 block 的任何地方,它的色调接近最小 0.0,而在您看到正常(对于 HSV)橙色/黄色/白色/等的地方,它的色调接近最大 1.0。由于未将 0-360 H channel 标准化为 0.0-1.0 导致的削波夸大了问题,但在修复后仍会存在。

关于python - 为什么从 RGB 到 HSV 的颜色转换会产生损坏的图像?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57198052/

相关文章:

python - 在 matplotlib 中将一个图像动画化到另一个图像之上

python - 如何用数据框中的所有行名称标记轴

Python 导入 matplotlib.pyplot 不起作用

python - 导入错误 : cannot import name 'Flask' from partially initialized module 'flask' (most likely due to a circular import)

python - 如何合并近似字符串?

python - Pandas 数据框 : get column item when the corresponding item in another column is greater than a value

Python Unicode 编码错误

c++ - 提高图像对比度

android - OpenCV for Android - 初始化矩阵

opencv - 如何将 SDL1 表面转换为 opencv Mat