在本教程中我们将学习如何使用由不同曝光设置拍摄的多张图像创建高动态范围High Dynamic RangeHDR图像。 我们将以 C++ 和 Python 两种形式分享代码。
什么是高动态范围成像
大多数数码相机和显示器都是按照 24 位矩阵捕获或者显示彩色图像。 每个颜色通道有 8 位因此每个通道的像素值在 0-255 范围内。 换句话说普通的相机或者显示器的动态范围是有限的。
但是我们周围世界动态范围极大。 在车库内关灯就会变黑直接看着太阳就会变得非常亮。 即使不考虑这些极端在日常情况下8 位的通道勉强可以捕捉到现场场景。 因此相机会尝试去评估光照并且自动设置曝光这样图像的最关注区域就会有良好的动态范围并且太暗和太亮的部分会被相应截取为 0 和 255。
在下图中左侧的图像是正常曝光的图像。 请注意由于相机决定使用拍摄主体我的儿子的设置所以背景中的天空已经完全流失了但是明亮的天空也因此被刷掉了。 右侧的图像是由 iPhone 生成的HDR图像。
High Dynamic Range (HDR)
iPhone 是如何拍摄 HDR 图像的呢 它实际上采用三种不同的曝光度拍摄了 3 张图像3 张图像拍摄非常迅速在 3 张图像之间几乎没有产生位移。然后组合三幅图像来产生 HDR 图像。 我们将在下一节看到一些细节。
将在不同曝光设置下获取的相同场景的不同图像组合的过程称为高动态范围HDR成像。
高动态范围HDR成像是如何工作的
在本节中我们来看下使用 OpenCV 创建 HDR 图像的步骤。
要想轻松学习本教程请点击此处下载 C++ 和 Python 代码还有图像。 如果您有兴趣了解更多关于人工智能计算机视觉和机器学习的信息请订阅我们的电子杂志。
第 1 步捕获不同曝光度的多张图像
当我们使用相机拍照时每个通道只有 8 位来表示场景的动态范围亮度范围。 但是通过改变快门速度我们可以在不同的曝光条件下拍摄多个场景图像。 大多数单反相机SLR有一个功能称为自动包围式曝光Auto Exposure BracketingAEB只需按一下按钮我们就可以在不同的曝光下拍摄多张照片。 如果你正在使用 iPhone你可以使用这个自动包围式 HDR 应用程序如果你是一个 Android 用户你可以尝试一个更好的相机应用程序。
场景没有变化时在相机上使用自动包围式曝光或在手机上使用自动包围式应用程序我们可以一张接一张地快速拍摄多张照片。 当我们在 iPhone 中使用 HDR 模式时会拍摄三张照片。
曝光不足的图像该图像比正确曝光的图像更暗。 目标是捕捉非常明亮的图像部分。
正确曝光的图像这是相机将根据其估计的照明拍摄的常规图像。
曝光过度的图像该图像比正确曝光的图像更亮。 目标是拍摄非常黑暗的图像部分。
但是如果场景的动态范围很大我们可以拍摄三张以上的图片来合成 HDR 图像。 在本教程中我们将使用曝光时间为1/30 秒0.25 秒2.5 秒和 15 秒的 4 张图像。 缩略图如下所示。
Auto Exposure Bracketed HDR image sequence
单反相机或手机的曝光时间和其他设置的信息通常存储在 JPEG 文件的 EXIF 元数据中。 查看此链接可在 Windows 和 Mac 中查看存储在 JPEG 文件中的 EXIF 元数据。 或者您可以使用我最喜欢的名为 EXIFTOOL 的查看 EXIF 的命令行工具。
我们先从读取分配到不同曝光时间的图像开始。
C++
void readImagesAndTimes(vector &images, vector ×)
{
int numImages = 4;
// 曝光时间列表
static const float timesArray[] = {1/30.0f,0.25,2.5,15.0};
times.assign(timesArray, timesArray + numImages);
// 图像文件名称列表
static