繁体   English   中英

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

[英]Why does the color conversion from RGB to HSV produce corrupt images?

我正在过滤掉某些颜色的图像,但是在使用hsv / hsl颜色空间时却陷入困境。 如果我尝试使用cv2.Color(image, cv2.COLOR_RGB2HSV)将使用matplotlib读取的图像转换为HSV cv2.Color(image, cv2.COLOR_RGB2HSV)则结果图像会像这样弄乱颜色: 图片

据我了解,图片应与原始图片一样显示 图片

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

我也尝试过使用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)

除了im之外,在运行代码时还得到以下警告:“将输入数据剪切为有效范围以显示具有RGB数据的imshow(浮点数为[0..1],整数为[0..255])。”

通过imshow文档

(M,N):具有标量数据的图像。 数据使用颜色图可视化。

(M,N,3):具有RGB值(0-1浮点或0-255整数)的图像。

(M,N,4):具有RGBA值(0-1浮点或0-255整数)的图像,即包括透明度。

这已经告诉您,无论您给它提供3个通道的矩阵(例如HSV),都将作为RGB图像。 这意味着,无论H中的数字是多少,都将作为R,依此类推。 因此,色相值将是红色,饱和度值将是绿色,色度值将是蓝色。

您提到的警告引起了我的注意,我决定进行测试,因为通常不使用matplotlib加载/显示图像。 我注意到的第一件事是图像使用的是float32类型,使用时从0-1开始:

image = mpimg.imread("imagePath.png")

没关系,对于OpenCV float32映像也是如此。

现在,如果您阅读cvtColor的文档并检查颜色转换,您将看到当图像类型为float32时,范围是:

H :[0-360]
S :[0-1.]
V :[0-1.]

因此,这意味着图像的第一个通道的大多数值都将高于1.,然后它将超出函数imshow(0-1)的浮动范围,该功能将对其进行裁剪,然后为1。

如我之前所说,该图像将被解释为RGB。 因此,“色相”通道将是“红色”通道,并且大多数值都是最大值,因此您的大多数图像将变成红色调。 绿色区域归因于饱和度大(接近最大值)。 但是,由于它是白色的地方,我想说的是您正在显示HLS,并且它是最大的L通道。

现在谈到这个问题,您期望得到什么结果? HSV色彩空间将始终为您显示与原始图像完全不同的事物,一切都取决于颜色,但是细微的变化(例如或多或少的饱和度)将为您提供更绿色的图像。

无论如何,如果您想显示更合理的内容,请将第一个通道除以360,将其缩放为0-1。 作为其他2个频道 但是,绿色部分不会消失,但看起来会少一些红色。

重要的结果是,色相(H)通道是一个连续的色环,在可视化HSV转换时应牢记。 即使当您由于不将0-360 H通道重新缩放为0.0-1.0以便使用matplotlib绘制为float32而修复裁剪时,这种阻塞也是不可避免的。

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

您实际上尚未发布原始图像,但是看起来像是matplotlib图中的屏幕截图,因此我无法完全重现您的效果。 但是,要查看效果,请仅将H通道与原始图像一起查看,我想您会明白我的意思:

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

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

您使用的是matplotlib,它需要RGB图像。 因此,色相显示为红色,饱和度显示为绿色,值显示为蓝色。 在所有看到非红色块的地方,Hue都接近最小0.0;在看到正常(对于HSV)的地方,橙色/黄色/白色/等处,这是Hue接近最大1.0的地方。 由于未将0-360 H通道标准化为0.0-1.0而导致的削波加剧了问题,但在解决此问题后仍然存在。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM