opencv,BGR2HSV创建了许多工件

2024-04-25 06:57:22 发布

您现在位置:Python中文网/ 问答频道 /正文

enter image description here

这张图片只是一个例子。右上角是原始图像,左上角是色调,左下角是饱和度,右下角是值。很容易看出H和S都充满了伪影。我想降低亮度,所以结果会选择很多这样的工件。

我做错什么了?

我的代码很简单:

vc = cv2.VideoCapture( 0 )
# while true and checking ret
ret, frame = vc.read()
frame_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.imshow("h", frame_hsv[:,:,0])
cv2.imshow("s", frame_hsv[:,:,1])
cv2.imshow("v", frame_hsv[:,:,2])

Tags: 代码图像图片色调cv2hsvframe例子
2条回答

我觉得你的问题有点误会。虽然博伊科·佩拉诺夫的回答肯定是正确的,但你提供的图片没有问题。其背后的逻辑如下:您的相机在RGB颜色空间中拍照,RGB颜色空间的定义是一个立方体。将其转换为HSV颜色空间时,所有像素都映射到以下圆锥体: HSV Cone

色调(HSV的第一个通道)是圆锥体上的角度,饱和度(HSV的第二个通道,在图像中称为色度)是到圆锥体中心的距离,值(HSV的第三个通道)是圆锥体上的高度。

色调通道通常定义在0-360之间,0处以红色开始(在8位图像的情况下,OpenCV使用0-180范围来适应the documentation中所述的无符号字符)。但问题是,值为0和359的两个像素在颜色上非常接近。当仅取外表面(饱和度最大时)来压平HSV锥时,更容易看到: Flattened HSV cone

即使这些值在感知上很接近(0时完全是红色,359时有一点紫色),这两个值也相差很远。这就是您在色调通道中描述的“工件”的原因。当OpenCV以灰度向您显示它时,它将黑色映射到0,白色映射到359。它们实际上是非常相似的颜色,但是当以灰度映射时,它们的显示距离太远。有两种方法可以绕过这个反直觉的事实:你可以用固定的饱和度和值将H通道重新投射到RGB空间,这将更接近我们的感知。你也可以使用另一个基于感知的颜色空间(比如Lab color space),这不会给你带来这些数学上的副作用。

博伊科·佩拉诺夫解释了这些人工制品补丁呈正方形的原因。JPEG压缩的工作原理是用更大的正方形替换像素,这些正方形近似于所替换的面片。如果在创建jpg时将压缩质量设置得很低,则可以看到这些方块甚至出现在RGB图像中。质量越低,正方形就越大,越明显。这些正方形的平均值是一个单一的值,对于红色的色调来说,可能会在0到5(显示为黑色)或355到359(显示为白色)之间结束。这就解释了为什么“文物”是方形的。

我们也可能会问自己,为什么在色调通道中会看到更多的JPEG压缩伪影。这是因为chroma subsampling,基于感知的研究表明,我们的眼睛比强度的快速变化更不容易看到颜色的快速变化。因此,在压缩时,JPEG故意丢失色度信息,因为我们无论如何都不会注意到它。

这个故事与饱和度(左下角的图像)的白色变化点类似。你描述的像素几乎是黑色的(在圆锥体的顶端)。因此,饱和度值可能变化很大,但不会对像素的颜色产生太大影响:它总是接近黑色。这也是HSV色彩空间不是纯粹基于感知的副作用。

RGB(或OpenCV的BGR)和HSV之间的转换(理论上)是无损的。你可以让自己相信这一点:重新转换你的HSV图像到RGB一,你得到的图像与你开始时完全一样,没有添加任何伪影。

您使用的是有损压缩图像,因此是矩形伪影。有了视频,你的曝光时间低,可以有带宽限制等,所以整体画面质量下降。你可以:

  • 通过使用Capture而不是VideoCapture来使用一系列静态快照,或者
  • 提取5-10个视频帧,并对其进行平均。

相关问题 更多 >