使用OpenCV和Python控制视频流的对比度和亮度

3
我正在使用OpenCV3和Python 3.7从我的网络摄像头捕获实时视频流,我想要控制亮度和对比度。我无法使用OpenCV的cap.set(cv2.CAP_PROP_BRIGHTNESS,float)cap.set(cv2.CAP_PROP_BRIGHTNESS,int)命令来控制相机设置,因此我想在读取每帧后应用对比度和亮度。每个捕获图像的Numpy数组为(480, 640, 3)。以下代码可以正确显示视频流,而无需尝试更改亮度或对比度。
import numpy as np
import cv2

cap = cv2.VideoCapture(0)    
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

当我使用Numpy的clip()方法控制对比度和亮度时,视频流会变得模糊,即使我设置contrast = 1.0(不改变对比度)和brightness = 0(不改变亮度)。以下是我的尝试来控制对比度和亮度。
import numpy as np
import cv2

cap = cv2.VideoCapture(0)
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    contrast = 1.0
    brightness = 0
    frame = np.clip(contrast * frame + brightness, 0, 255)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

如何使用OpenCV控制视频流的对比度和亮度?

2个回答

4

我使用了numpy.clip()方法找到了解决方案,@fmw42提供了使用cv2.normalize()方法的解决方案。我更喜欢cv2.normalize()的解决方案,因为它将像素值归一化到0-255而不是在0或255处裁剪它们。这里提供了两种解决方案。

cv2.normalize()解决方案:

  • Brightness-以相同的量移动alpha和beta值。 alpha可以是负数,beta可以大于255。(如果alpha≥255,则图片变白,如果beta≤0,则图片变黑。)
  • Contrast-扩大或缩短alpha和beta之间的差距。

以下是代码:

import numpy as np
import cv2

cap = cv2.VideoCapture(0)
while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    cv2.normalize(frame, frame, 0, 255, cv2.NORM_MINMAX)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

numpy.clip()的解决方案:

这个方法帮助我解决了这个问题:如何使用Python+OpenCV快速更改图像亮度?。需要执行以下操作:

  1. 首先将红绿蓝(RGB)转换为色调饱和度值(HSV)(“值”相当于“亮度”)
  2. 对Numpy数组中的“Value”部分进行“切片”,并在该切片上调整亮度和对比度
  3. 再将其从HSV转换回RGB。

这是可行的解决方案。可以更改contrastbrightness值。 numpy.clip()确保所有像素值都在各个通道(R,G和B)中保持在0到255之间。

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    frame = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    contrast = 1.25
    brightness = 50
    frame[:,:,2] = np.clip(contrast * frame[:,:,2] + brightness, 0, 255)
    frame = cv2.cvtColor(frame, cv2.COLOR_HSV2BGR)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

1
你可以使用cv2.normalize()函数来改变图像的亮度和对比度。 - fmw42
@fmw42 - 我在我的答案中加入了您的解决方案。我更喜欢cv2.normalize()而不是numpy.clip(),因为cv2.normalize()不会剪切边缘。谢谢! - slalomchip
1
如果您想要更多的对比度或亮度,可以在cv2.normalize中使用alpha和beta来处理值超出0至255范围的情况。例如:cv2.normalize(hist, None, alpha=0, beta=1.5*255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U) - fmw42

1
import cv2 as cv

cap = cv.VideoCapture(0)

while True:
    # Capture frame-by-frame
    ret, frame = cap.read()
    # normalize the frame
    frame = cv.normalize(
        frame, None, alpha=0, beta=255, norm_type=cv.NORM_MINMAX, dtype=cv.CV_8UC1
    )
    # Display the resulting frame
    cv.imshow("frame", frame)
    # press q to quit
    if cv.waitKey(1) & 0xFF == ord("q"):
        break

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接