目录

1 什么是曝光融合

2 曝光融合的原理

3 代码与结果

4 参考


本教程中,我们将了解使用OpenCV的Exposure Fusion(曝光融合)。

1 什么是曝光融合

曝光融合是一种将使用不同曝光设置拍摄的图像合成为一张看起来像色调映射的高动态范围(HDR)图像的图像的方法。当我们使用相机拍摄照片时,每个颜色通道只有8位来表示场景的亮度。然而,我们周围世界的亮度理论上可以从0(黑色)到几乎无限(直视太阳)。因此,傻瓜相机或移动相机根据场景决定曝光设置,以便使用相机的动态范围(0-255值)来表示图像中最有趣的部分。例如,在许多相机中,使用面部检测来查找面部并设置曝光,使得面部看起来很好。这引出了一个问题-我们可以在不同的曝光设置下拍摄多张照片并拍摄更大范围的场景亮度吗?答案是肯定的。传统上使用HDR成像然后进行色调映射的方式。具体见上篇文章:

https://blog.csdn.net/LuohenYJ/article/details/89712234

HDR成像要求我们知道精确的曝光时间。HDR图像本身看起来很暗,看起来不太漂亮。DR图像中的最小强度为0,但理论上没有最大值。所以我们需要将其值映射到0到255之间,以便我们可以显示它。将HDR图像映射到常规的每通道8位彩色图像的过程称为色调映射。如您所见,组装HDR图像和色调映射有点麻烦。我们不能不使用HDR就使用多个图像创建色调映射图像。结果证明我们可以用曝光融合来实现。

2 曝光融合的原理

应用曝光融合的步骤如下所述:

(1) 使用不同曝光拍摄多张图像

首先,我们需要在不移动相机的情况下捕获同一场景的一系列图像。如上所示,序列中的图像具有不同的曝光。这是通过改变相机的快门速度来实现的。通常,我们选择一些曝光不足的图像,一些曝光过度的图像和一个正确曝光的图像。

在“正确”曝光的图像中,选择快门速度(由相机或摄影师自动选择),以便每通道8位动态范围用于表示图像中最有趣的部分。太暗的区域被剪切为0,而太亮的区域被饱和到255。

在曝光不足的图像中,快门速度很快,图像很暗。因此,图像的8位用于捕获亮区域,而暗区域被剪切为0。在曝光过度的图像中,快门速度较慢,因此传感器捕获的光线更多,因此图像更亮。传感器的8位用于捕获暗区域的强度,而亮区域饱和到255的值。大多数单反相机都有一个称为自动曝光包围(AEB)的功能,只需按一下按钮,我们就可以在不同曝光下拍摄多张照片。当我们在iPhone中使用HDR模式时,它需要三张照片(安卓可以下载超级相机这个软件)。

(2) 图像对齐

即使使用三脚架获取序列中的图像也需要对齐,因为即使较小的相机抖动也会降低最终图像的质量。OpenCV提供了一种使用对齐这些图像的简便方法AlignMTB。该算法将所有图像转换为中值阈值位图(MTB)。通过将值1分配给比中值亮度更亮的像素来计算图像的MTB,否则为0。MTB 对曝光时间不变。因此,可以对准MTB而无需我们指定曝光时间。

(3) 图像融合

具有不同曝光的图像捕获不同范围的场景亮度。根据Tom Mertens,Jan Kautz和Frank Van Reeth 题为Exposure Fusion的论文。论文见:

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.64.7616&rep=rep1&type=pdf

曝光融合通过仅保留多重曝光图像序列中的“最佳”部分来计算所需图像。

作者提出了三个质量指标:

1曝光良好:如果序列中的图像中的像素接近零或接近255,则不应使用该图像来查找最终像素值。其值接近中间强度(128)的像素是比较合适的。

2对比度:高对比度通常意味着高品质。因此,对于该像素,给予特定像素的对比度值高的图像具有更高的权重。

3饱和度:类似地,更饱和的颜色更少被淘汰并且代表更高质量的像素。因此,特定像素的饱和度高的图像被赋予该像素的更高权重。

三种质量度量用于创建权重图,该权重图表示图像在位置处的像素的最终强度中的贡献。对权重图进行归一化,使得对于任何像素,所有图像的贡献总计为1。

结合权重图使用以下等式组合图像是很有效的:

其中,是原始图像,是输出图像。问题在于,由于像素是从不同曝光的图像中拍摄的,因此使用上述等式获得的输出图像将显示许多裂缝。该论文的作者使用拉普拉斯金字塔来混合图像。我们将在以后的文章中介绍这项技术的细节。

幸运的是使用OpenCV,这种图像曝光融合合并只是使用MergeMertens该类的两行代码。请注意,这个名字取决于Exposure Fusion论文的第一作者Tom Mertens 。

3 代码与结果

代码地址:

https://github.com/luohenyueji/OpenCV-Practical-Exercise

C++:

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
#include <fstream>
using namespace cv;
using namespace std;// Read Images
void readImages(vector<Mat> &images)
{int numImages = 16;static const char* filenames[] ={"image/memorial0061.jpg","image/memorial0062.jpg","image/memorial0063.jpg","image/memorial0064.jpg","image/memorial0065.jpg","image/memorial0066.jpg","image/memorial0067.jpg","image/memorial0068.jpg","image/memorial0069.jpg","image/memorial0070.jpg","image/memorial0071.jpg","image/memorial0072.jpg","image/memorial0073.jpg","image/memorial0074.jpg","image/memorial0075.jpg","image/memorial0076.jpg"};//读图for (int i = 0; i < numImages; i++){Mat im = imread(filenames[i]);images.push_back(im);}
}int main()
{// Read images 读取图像cout << "Reading images ... " << endl;vector<Mat> images;//是否图像映射bool needsAlignment = true;// Read example images 读取例子图像readImages(images);//needsAlignment = false;// Align input imagesif (needsAlignment){cout << "Aligning images ... " << endl;Ptr<AlignMTB> alignMTB = createAlignMTB();alignMTB->process(images, images);}else{cout << "Skipping alignment ... " << endl;}// Merge using Exposure Fusion 图像融合cout << "Merging using Exposure Fusion ... " << endl;Mat exposureFusion;Ptr<MergeMertens> mergeMertens = createMergeMertens();mergeMertens->process(images, exposureFusion);// Save output image 图像保存cout << "Saving output ... exposure-fusion.jpg" << endl;imwrite("exposure-fusion.jpg", exposureFusion * 255);return 0;
}

Python:

import cv2
import numpy as np
import sysdef readImagesAndTimes():filenames = ["image/memorial0061.jpg","image/memorial0062.jpg","image/memorial0063.jpg","image/memorial0064.jpg","image/memorial0065.jpg","image/memorial0066.jpg","image/memorial0067.jpg","image/memorial0068.jpg","image/memorial0069.jpg","image/memorial0070.jpg","image/memorial0071.jpg","image/memorial0072.jpg","image/memorial0073.jpg","image/memorial0074.jpg","image/memorial0075.jpg","image/memorial0076.jpg"]images = []for filename in filenames:im = cv2.imread(filename)images.append(im)return imagesif __name__ == '__main__':# Read imagesprint("Reading images ... ")if len(sys.argv) > 1:# Read images from the command lineimages = []for filename in sys.argv[1:]:im = cv2.imread(filename)images.append(im)needsAlignment = Falseelse :# Read example imagesimages = readImagesAndTimes()needsAlignment = False# Align input imagesif needsAlignment:print("Aligning images ... ")alignMTB = cv2.createAlignMTB()alignMTB.process(images, images)else :print("Skipping alignment ... ")# Merge using Exposure Fusionprint("Merging using Exposure Fusion ... ");mergeMertens = cv2.createMergeMertens()exposureFusion = mergeMertens.process(images)# Save output imageprint("Saving output ... exposure-fusion.jpg")cv2.imwrite("exposure-fusion.jpg", exposureFusion * 255)

本文第一张图获得的不同曝光的图像,通过这种方法所得结果如下:

在输入图像中,我们可以获得过度曝光图像中光线昏暗区域和曝光不足图像中明亮区域的细节。但是,在合并的输出图像中,像素在图像的每个部分都具有明亮的细节。我们还可以在之前的帖子中看到我们用于HDR成像的图像的这种效果。用于产生最终输出的四个图像显示在左侧,输出图像显示在右侧。结果如下图所示:

正如您在本文中所看到的,Exposure Fusion允许我们在不明确计算HDR图像的情况下实现类似于HDR + Tonemapping的效果。因此,我们不需要知道每张图像的曝光时间,但我们能够获得非常合理的结果。那么,为什么要费心去做HDR呢?好吧,在很多情况下,Exposure Fusion产生的输出可能不符合您的喜好。没有旋钮可以调整以使其变得不同或更好。另一方面,HDR图像捕获场景的原始亮度。如果您不喜欢色调映射的HDR图像,请尝试使用不同的色调映射算法。总之,Exposure Fusion代表了一种权衡。在速度和不太严格的要求下使得算法更加灵活(例如,不需要暴露时间)

4 参考

https://www.learnopencv.com/exposure-fusion-using-opencv-cpp-python/

[OpenCV实战]24 使用OpenCV进行曝光融合相关推荐

  1. [OpenCV实战]47 基于OpenCV实现视觉显著性检测

    人类具有一种视觉注意机制,即当面对一个场景时,会选择性地忽略不感兴趣的区域,聚焦于感兴趣的区域.这些感兴趣的区域称为显著性区域.视觉显著性检测(Visual Saliency Detection,VS ...

  2. [OpenCV实战]52 在OpenCV中使用颜色直方图

    颜色直方图是一种常见的图像特征,顾名思义颜色直方图就是用来反映图像颜色组成分布的直方图.颜色直方图的横轴表示像素值或像素值范围,纵轴表示该像素值范围内像素点的个数或出现频率.颜色直方图属于计算机视觉中 ...

  3. [OpenCV实战]39 在OpenCV中使用ArUco标记的增强现实

    文章目录 1 什么是ArUco标记? 2 在OpenCV中生成ArUco标记 3 检测Aruco标记 4 增强现实应用 5 总结和代码 5.1 生成aruco标记 5.2 使用aruco增强现实 6 ...

  4. [OpenCV实战]29 使用OpenCV实现红眼自动去除

    目录 1 红眼消除 1.1 眼部检测 1.2 红眼遮掩 1.3 清除瞳孔掩模空洞 1.4 红眼修复 2 结果与完整代码 2.1 结果 2.2 代码 3 参考 在本教程中,我们将学习如何完全自动地从照片 ...

  5. opencv曝光过度_使用 OpenCV 进行曝光融合(Exposure Fusion)成像

    在本教程中,我们将学习使用OpenCV的Exposure Fusion.我们将使用C ++和Python共享代码. 什么是曝光融合?曝光融合是一种将使用不同曝光设置拍摄的图像组合成一个看起来像色调映射 ...

  6. 再次升级,985博士整理的71个OpenCV实战项目教程开放下载!

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 近期小白学视觉公众号推出了多篇Python+OpenCV实战项目的 ...

  7. 实战:OpenVINO+OpenCV 文本检测与识别

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|OpenCV学堂 模型介绍 文本检测模型 OpenVIN ...

  8. 基于OpenCV实战:提取中心线

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自|AI算法与图像处理 问题 前几天有个人问了我一个问题,问 ...

  9. Opencv实战 | 用摄像头自动化跟踪特定颜色物体

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:新机器视觉 1. 导语 在之前的某个教程里,我们探讨了如 ...

最新文章

  1. MySQL5.6 主从复制配置
  2. 【Prince2科普】Prince2的七大原则(5)
  3. 2020年第十一届蓝桥杯 - 省赛 - C/C++研究生组 - F.成绩分析
  4. Github git 命令下载加速
  5. 计算机组成西电裘答案,西电计算机组成原理.ppt
  6. 实现Runnable 创建多线程的简单实现
  7. bagging算法_Bagging/Boosting傻傻分不清?来一探究竟吧~
  8. 什么是函数式编程思维?
  9. USB接口芯片的选型参考(转贴)
  10. 简单介绍一下用加速度传感器修正角速度传感器(陀螺仪)累计误差的原理
  11. 新一配:如何对电脑配置进行评判【转载】
  12. 服务器无线组网,物联网无线组网介绍
  13. 阿里云OSS对象存储
  14. 社群怎么建立,怎么做好社群营销?
  15. HTML侧面导航栏效果
  16. html保存时出现nul,c# – 有时保存的文件只包含NUL字符
  17. 东华oj-进阶题第87题-挤牛奶
  18. RSA---n分解攻击
  19. android eclipse计算器布局,请教eclipse android 简单计算器入门 相关问题。
  20. Java 数组排序工具类

热门文章

  1. 1--100以内的质数(只能被1和其本身整除的数就是质数,1不是质数)
  2. 【滤波跟踪】Singer-Kalman模型下的机动目标跟踪算法含Matlab源码
  3. 29 Linux 防火墙
  4. pdf转换器在线转换详细教程
  5. 【面试题笔记-Java】MySQL数据库、索引、MVCC等知识点(自己整理)
  6. 【MATLAB】高塔观测数据通量梯度法计算感热及潜热通量
  7. 模拟360导航的钢琴效果实现
  8. 利用隧道感受IPV6
  9. java8 四大函数式接口 和 用于数据处理的 stream流 使用详解
  10. STM32配置单片机系统时钟(转)