opencv,BGR2HSV创建了大量的工件

时间:2013-06-21 15:43:19

标签: python opencv image-processing hsv

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])

2 个答案:

答案 0 :(得分:10)

我觉得你的问题存在误解。虽然Boyko Peranov的答案肯定是正确的,但您提供的图像没有问题。其背后的逻辑如下:您的相机在RGB色彩空间中拍照,根据定义,它是一个立方体。将其转换为HSV颜色空间时,所有像素都映射到以下锥形: HSV Cone

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

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

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

Boyko Peranov解释了这些伪影贴片是正方形的原因。 JPEG压缩的工作原理是将像素替换为近似于它所替换的补丁的较大的正方形。如果在创建jpg时将压缩质量设置得很低,则可以看到这些方块甚至出现在RGB图像中。质量越低,方块越大,越明显。这些方块的平均值是单个值,对于红色的色调,可能最终在0到5之间(显示为黑色)或355和359(显示为白色)。这就解释了为什么“文物”是方形的。

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

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

RGB(或OpenCV的BGR)与HSV之间的转换(理论上)是无损的。您可以说服自己:将您的HSV图像重新转换为RGB图像,您可以获得与开始时完全相同的图像,不会添加任何工件。

答案 1 :(得分:3)

您正在使用有损压缩图像,因此使用矩形工件。使用视频时,您的曝光时间较短,可能会出现带宽限制等情况。因此整体图像质量会下降。你可以:

  • 使用Capture代替VideoCapture
  • ,使用一系列静态照片
  • 提取5-10个视频帧,并对其进行平均。