使用opencv关闭相机自动曝光的问题

您所在的位置:网站首页 小米11摄像头曝光怎么设置的 使用opencv关闭相机自动曝光的问题

使用opencv关闭相机自动曝光的问题

2024-07-15 14:25| 来源: 网络整理| 查看: 265

项目场景:

项目需要在较暗的光照环境下使用USB相机实时拍着视频,且需要保证相机跑满30帧。如果使用相机默认的自动曝光设置,会因为低光照而自动延长曝光时间,最终导致拍摄帧率只有15帧左右。因此,需要通过OpenCV控制相机关闭自动曝光,并设置手动的曝光参数,以限制实际的曝光时间。从而在部分牺牲拍摄亮度的情况下换取更高的拍摄帧率。

系统环境:win10、ubuntu20.04 OpenCV版本:均为4.7.0

问题描述

软件需要兼容win10、ubuntu20.04,最初在win10上编写和调试。 按照网上的教程,使用cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, value) 设置曝光时,value在0-2.6为手动曝光,2.6-4为自动曝光。于是写了如下代码:

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) exposure = -5 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 3.0) # 先打开自动曝光 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) # 再关闭自动曝光 cap.set(cv2.CAP_PROP_EXPOSURE, exposure) # 最后设置曝光参数

测试时发现,相机拍到的图像有时候会变得非常暗。远比使用相机调试软件设置相同参数下拍到的图像暗。并且时而正常时而不正常。

经过多次测试发现,当使用windows系统自带的相机打开USB相机并关闭后,再使用自己编写的程序可以以正常的曝光亮度打开相机一次。但重启自己编写的程序后相机的图像又会变得非常暗。所以,基本可以推测自己的程序设置的参数可能有问题。

于是又自己测试了一遍cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, value) 参数。奇怪的是在设置value为1.0时可以打开自动曝光,而在设置value为0.0时可以关闭自动曝光??? 然后把代码改成

cap = cv2.VideoCapture(0, cv2.CAP_DSHOW) exposure = -5 # 我这里取-5时相机刚好能达到30帧 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) # 先打开自动曝光 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.0) # 再关闭自动曝光 cap.set(cv2.CAP_PROP_EXPOSURE, exposure) # 最后设置曝光参数

相机的帧率和亮度一切看起来都正常了。

然而当开始把代码搬到ubuntu上调试的时候一切问题又重来了。相机的图像又变得非常暗,甚至比在win10上出问题时还要暗。出问题的代码如下:

cap = cv2.VideoCapture(0, cv2.CAP_V4L2) exposure = 300 # linux的曝光参数计算和windows不太一样,我这里取大约300时相机刚好达到30帧 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) # 先打开自动曝光 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.0) # 再关闭自动曝光 cap.set(cv2.CAP_PROP_EXPOSURE, exposure) # 最后设置曝光参数

一番折腾之后,把cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, value)的参数改回:

cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 3.0) # 先打开自动曝光 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) # 再关闭自动曝光

拍摄的图像又恢复正常了。

解决方案:

经过测试发现,在windows下,以下参数是正常工作的:

cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) # 打开自动曝光 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.0) # 关闭自动曝光

在ubuntu下,以下参数是正常工作的:

cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 3.0) # 打开自动曝光 cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) # 关闭自动曝光

推测网上主流的教程是以linux系统写的。这个问题目前不确定是系统差异还是OpenCV的bug(毕竟一个开关量用0~4之间的数表示感觉十分反直觉)。 最后,顺带一提cap.set(cv2.CAP_PROP_EXPOSURE, exposure) 设置手动曝光时windows和linux上exposure参数的换算。直观上感觉linux的exposure比较接近快门时间ms数×10。和windows上的曝光参数大致可按

exposure_linux≈10000*2^(exposure_win)

换算

目前可用的程序

import cv2 import os import numpy as np import sys import time def TakePictures(fileName = '', dirPath='.'): framesSkip = 30 FPS = 999 interval_ms = 1000.0 / FPS - 1; manualExposure = -5 inputSrc = 0 if sys.platform.startswith('win'): cap = cv2.VideoCapture(int(inputSrc), cv2.CAP_DSHOW) elif sys.platform.startswith('linux'): cap = cv2.VideoCapture(int(inputSrc), cv2.CAP_V4L2) else: print('Unknow System') return cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080) cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')) # 打开自动曝光 if sys.platform.startswith('win'): cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) elif sys.platform.startswith('linux'): cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 3.0) cap.set(cv2.CAP_PROP_AUTO_WB, 1.0) # 打开自动白平衡 cap.set(cv2.CAP_PROP_AUTO_WB, 1.0) for i in range(framesSkip): cap.read(); time.sleep(interval_ms / 1000); # 关闭自动曝光 # 并设置手动曝光参数 if sys.platform.startswith('win'): cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.0) cap.set(cv2.CAP_PROP_EXPOSURE, manualExposure) elif sys.platform.startswith('linux'): cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 1.0) # 关闭自动曝光 cap.set(cv2.CAP_PROP_EXPOSURE, 10000 * 2**manualExposure) n = 1 goon, frame = cap.read() # print('size: %d x %d' % (frame.shape[1], frame.shape[0])) cv2.namedWindow('camera', 0) dt = interval_ms / 1000 t0 = time.time() while goon: cv2.imshow('camera', frame) key = cv2.waitKey(2) if key == 13: #ENTER if fileName == '': saveFileName = os.path.join(dirPath, 'pic_%04d.png' % (n,)) cv2.imwrite(saveFileName, frame) n += 1 else: saveFileName = os.path.join(dirPath, fileName) cv2.imwrite(saveFileName, frame) break print('save: ', saveFileName) elif key == 27 or key == ord('q'): #ESC break goon, frame = cap.read() t1 = time.time() dt += (t1 - t0 - dt) * 0.1 t0 = t1 print('FPS = %f' % (1.0/dt), end='\r') cap.release() cv2.destroyAllWindows() if __name__ == '__main__': TakePictures()


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3