在 OpenCV 和 Python 中控制视频流的对比度和亮度

Posted

技术标签:

【中文标题】在 OpenCV 和 Python 中控制视频流的对比度和亮度【英文标题】:Controlling Contrast and Brightness of Video Stream in OpenCV and Python 【发布时间】:2020-04-03 17:07:00 【问题描述】:

我正在使用 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 控制视频流的对比度和亮度?

【问题讨论】:

【参考方案1】:

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

cv2.normalize() 解决方案:

亮度 - 将 alpha 和 beta 值移动相同的量。 Α 可以是负数,beta 可以高于 255。(如果 alpha >= 255, 则图片为白色,如果 beta 对比度 - 扩大或缩短 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() 解决方案:

这帮助我解决了问题:How to fast change image brightness with python + OpenCV?。我需要:

    首先将红绿蓝 (RGB) 转换为色相饱和度值 (HSV) (“值”与“亮度”相同) 将 Numpy 数组“切片”到 Numpy 数组的 Value 部分,并调整该切片的亮度和对比度 从 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()

【讨论】:

你可以用 cv2.normalize() 改变亮度和对比度 @fmw42 - 我将您的解决方案添加到我的答案中。我比numpy.clip() 更喜欢cv2.normalize(),因为cv2.normalize() 不会剪裁边缘。谢谢! 如果您想要更多的对比度或亮度,您可以在 cv2.normalize 中使用 0 到 255 范围之外的值的 alpha 和 beta。例如cv2.normalize(hist, None, alpha=0, beta=1.5*255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)【参考方案2】:
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

【讨论】:

以上是关于在 OpenCV 和 Python 中控制视频流的对比度和亮度的主要内容,如果未能解决你的问题,请参考以下文章

opencv获取fps为0

OpenCV入门(C++/Python)- 使用OpenCV读取和编写视频

[OpenCV-Python] OpenCV 中视频分析 部分 VI

在 python-opencv 中获取视频尺寸

Python opencv 无法从视频中裁剪帧

使用python和opencv进行视频分析:输入视频是颠倒的