目录
opencv -Camera曝光设置
1.曝光设置
cv_cap.set(cv::CAP_PROP_AUTO_EXPOSURE, 0.25); // where 0.25 means "manual exposure, manual iris"
cv_cap.set(CV_CAP_PROP_EXPOSURE, -13);
2.设置自动曝光为手动曝光
cv_cap.set(cv::CAP_PROP_AUTO_EXPOSURE, 0.25); // where 0.25 means "manual exposure, manual iris"
3.曝光参数具体对应于曝光时间
OpenCV_exposure | 快门时间ms |
-1 | 640 |
-2 | 320 |
-3 | 160 |
-4 | 80 |
-5 | 40 |
-6 | 20 |
-7 | 10 |
-8 | 5 |
-9 | 2.5 |
-10 | 1.25 |
-11 | 0.625 |
-12 | 0.3125 |
-13 | 0.15625 |
-14 | 0.078125 |
说明:x为opencv中设置的曝光值OpenCV_exposure
y为快门时间
4.代码实现
void cameExposureTestAndExposureFusionTest(VideoCapture cap)
{
int ix = 0;
int numImages = 4;
Mat frame;
vector<Mat> images;
//是否图像映射
bool needsAlignment = true;
//cap.set()
auto i = cap.get(CAP_PROP_EXPOSURE);
cout << "设置之前曝光为:" << i << endl;
cap.set(CAP_PROP_AUTO_EXPOSURE, 0.25);
while (waitKey(30) != 27)
{
/*
int 循环调节 = -13;
while (1)
{
if (循环调节 == 0)
{
循环调节 = -13;
break;
}
//cout << "设置之后曝光为:" << cap.get(CAP_PROP_EXPOSURE);
cap.set(CAP_PROP_EXPOSURE, 循环调节);
//cout << "设置之后曝光为:" << cap.get(CAP_PROP_EXPOSURE)<<endl;
cap >> frame;
putText(frame, "Exposure:" + to_string(循环调节), Point(20, 30), 3, 1.0, Scalar(255, 0, 0));
imshow("调用摄像头", frame);
imwrite("E:\\Project_OpenCV_C++\\openCV_Test1\\openCV_Test3\\cameExposureTest\\" + to_string(循环调节) + ".jpg", frame);
waitKey(30);
images.push_back(frame);
循环调节= 循环调节+1;
}
*/
vector<float> times;
// 曝光时间列表
const float timesArray[] = { 1 / 30.0f,0.25,2.5,15.0 };
times.assign(timesArray, timesArray + numImages);
// 曝光值列表
float OpenCV_exposure[] = {NULL };
//这里将快门时间转换成OpenCV的曝光参数
for (ix = 0; ix < 4; ix++)
{
OpenCV_exposure[ix] = -(log(640 / (timesArray[ix]*1000) ) + 1);
}
for (ix=0; ix<4; ix++)
{
cap.set(CAP_PROP_EXPOSURE, OpenCV_exposure[ix]);
cap >> frame;
imshow("调用摄像头", frame);
imwrite("E:\\Project_OpenCV_C++\\openCV_Test1\\openCV_Test3\\cameExposureTest\\" + to_string(ix) + ".jpg", frame);
waitKey(30);
images.push_back(frame);
}
// Align input images
if (needsAlignment)
{
cout << "Aligning images ... " << endl;
Ptr<AlignMTB> alignMTB = createAlignMTB();
alignMTB->process(images, images);
}
else
{
cout << "Skipping alignment ... " << endl;
}
// 获取图像响应函数 (CRF)
Mat responseDebevec;
Ptr<CalibrateDebevec> calibrateDebevec = createCalibrateDebevec();
calibrateDebevec->process(images, responseDebevec, times);
// Merge using Exposure Fusion 图像融合
cout << "Merging using Exposure Fusion ... " << endl;
Mat exposureFusion;
Ptr<MergeMertens> mergeMertens = createMergeMertens();
mergeMertens->process(images, exposureFusion);
imwrite("E:\\Project_OpenCV_C++\\openCV_Test1\\openCV_Test3\\cameExposureTestAndExposureFusionTest\\exposure-fusion.jpg", exposureFusion*255);
// 将图像合并为HDR线性图像
Mat hdrDebevec;
Ptr<MergeDebevec> mergeDebevec = createMergeDebevec();
mergeDebevec->process(images, hdrDebevec, times, responseDebevec);
// 保存图像
imwrite("E:\\Project_OpenCV_C++\\openCV_Test1\\openCV_Test3\\cameExposureTestAndExposureFusionTest\\hdrDebevec.hdr", hdrDebevec);
// 使用Drago色调映射算法获得24位彩色图像
Mat ldrDrago;
Ptr<TonemapDrago> tonemapDrago = createTonemapDrago(1.0, 0.7);
tonemapDrago->process(hdrDebevec, ldrDrago);
ldrDrago = 3 * ldrDrago;
imwrite("E:\\Project_OpenCV_C++\\openCV_Test1\\openCV_Test3\\cameExposureTestAndExposureFusionTest\\ldr-Drago.jpg", ldrDrago * 255);
// 使用Durand色调映射算法获得24位彩色图像
/*
Mat ldrDurand;
Ptr<TonemapDurand> tonemapDurand = createTonemapDurand(1.5, 4, 1.0, 1, 1);
tonemapDurand->process(hdrDebevec, ldrDurand);
ldrDurand = 3 * ldrDurand;
imwrite("E:\\Project_OpenCV_C++\\openCV_Test1\\openCV_Test3\\cameExposureTestAndExposureFusionTest\\ldr-Durand.jpg", ldrDurand * 255);
*/
// 使用Reinhard色调映射算法获得24位彩色图像
Mat ldrReinhard;
Ptr<TonemapReinhard> tonemapReinhard = createTonemapReinhard(1.5, 0, 0, 0);
tonemapReinhard->process(hdrDebevec, ldrReinhard);
imwrite("E:\\Project_OpenCV_C++\\openCV_Test1\\openCV_Test3\\cameExposureTestAndExposureFusionTest\\ldr-Reinhard.jpg", ldrReinhard * 255);
// 使用Mantiuk色调映射算法获得24位彩色图像
Mat ldrMantiuk;
Ptr<TonemapMantiuk> tonemapMantiuk = createTonemapMantiuk(2.2, 0.85, 1.2);
tonemapMantiuk->process(hdrDebevec, ldrMantiuk);
ldrMantiuk = 3 * ldrMantiuk;
imwrite("ldr-Mantiuk.jpg", ldrMantiuk * 255);
imwrite("E:\\Project_OpenCV_C++\\openCV_Test1\\openCV_Test3\\cameExposureTestAndExposureFusionTest\\ldr-Mantiuk.jpg", ldrMantiuk * 255);
images.clear();
}
return;
}
5.其他知识补充
5.1.相机曝光原理
首先来看一下摄像成像的原理,摄像成像即是光进入相机,打在相机里的感光元件,这样光就在感光元件上留下了痕迹,这个光的痕迹最终的表现形式就照片。
摄影成像的曝光分为三种,一种是曝光不足,就是整个照片过暗了;曝光正常,即整个照片敏感正常;曝光过度,也称为过曝,即整个照片过亮。
所以可以简单把曝光值理解为这个值控制着照片整体的明暗。对于曝光这个词的正经解释是一切光化学成像方法的基本过程。
三个因素会对最终的曝光值产生影响,即Aperture光圈、Shutter Speed快门速度、ISO感光度。首先说下光圈的含义,光圈是控制镜头进光量的装置,即是下图中由几块扇叶组成的圆洞,圆洞大进光量就大,圆洞小进光量就小。
可以把光想象成水,把最终的感光元件想象成一张纸,适量的水浸湿这张纸,也就是适量的光打到感光元件上,就是曝光正常,也就是明暗正常的一张照片。
光圈就好像控制进水量的闸门,闸门开大,水量太大,有过多的水浸湿纸面,纸面上的痕迹就没办法成型;闸门比较小,水量太小,纸面上的痕迹就过浅看不清。
5.2.快门速度
接下来说说快门速度,下图中镜头处遮住感光元件的就是快门,快门就好像一道完全不透光的门帘,当快门拉下的时候,光完全不能打到感光元件上。
快门抬起-光打到感光元件上-快门再落下的这一过程是比较快的,一般只有几分之一秒。在相机技术还并不发达的时期,例如上个世纪,这个过程是比较慢的,例如需要几十分钟,而现在快门速度可以这么快是因为感光元件的ISO,即感光度比较高,这个我们在本文后续进行讲解。
可以把快门速度想象成开闸关闸的时间间隔,结合上文对光圈大小代表闸门大小的想象,可以很容易理解,最终接触到纸的水量,也就是打到感光元件上的光量,由闸门大小和开闸关闸的时间间隔同时控制。
但是这两个又有所不同,快门速度和光圈的大小可产生的物理特性是不同的。例如光圈越大,孔径越大,那么背景虚化能力越强,这跟小孔成像的原理很类似,小孔越小,越清晰,反之就越模糊。
对于运动中的物体,快门速度越快,运动中的物体就会越清晰,而不会因为运动而产生模糊,而为了达到正常的曝光值,让照片明暗正常,可能就需要修改光圈和ISO。
ISO感光度是传感器的一个参数,表示每个像素接受光信息能力的强弱,光圈快门都不变的情况下,获得光信息的能力越强则能在同等条件下获得更高的曝光,因为它可以获得抓到更多光信息。可以把ISO想象成一张纸的纸质,有的纸张是吸水能力较强的,有的纸张的吸水能力是较差的,相同的给水量,较差吸水能力的纸无法成像,而吸水能力强的纸又可能吸了太多的水,导致成像效果不好。一般ISO是很少调整的,高ISO数值可能导致画面噪点过多。
综上所述,Aperture光圈、Shutter Speed快门速度、ISO感光度三个参数共同决定最终曝光值。但其实有时我们只想要一个正常的曝光值,而并不想非常麻烦的对三个参数进行精确控制,避免错误参数导致的成像效果不好。此时就出现了自动曝光,就是说相机自动根据当前的画面给一个系统判定的比较合适的曝光值,而三个参数具体为何,由相机自动计算。这就牵扯到一个过程,即是对当前画面进行的亮度判定,简称测光。这个测光在HDRP里面分成三种模式(在一般相机里也差不多一个意思),Average、Spot、Center Weighted,Average既是以画面整体作为测光参考。
Spot即是只以画面中央的圆圈内的亮度,作为测光的依据,只保证中间小圆内的画面曝光正常,当拍摄的画面只需要保证中间物体明暗正常时,建议采用此模式。
Center Weighted以画面中央部分的亮度作为主要参考,以画面边缘部分的亮度作为次要参考,也就是说中间部分权重高,边缘部分权重低,中间和边缘的中间部分的权重有一个过渡。