opencv-python图像增强四:多曝光融合(方法一)

文章目录


一、简介:

在摄影和计算机视觉领域,高动态范围(HDR)技术已经成为了捕捉丰富细节和真实感图像的重要手段。然而,要实现高质量的HDR效果,我们需要对多张不同曝光时间的图像进行融合处理。本文将探讨多曝光融合技术的基本原理和应用,帮助您深入了解这一技术如何捕捉更丰富、更真实的世界。

在自然界中,我们的眼睛能够感知从最暗到最亮的广阔亮度范围。然而,传统的相机传感器和显示设备却无法捕捉到这一完整的亮度范围,导致图像在亮度上出现失真。为了解决这一问题,HDR技术应运而生。HDR技术通过拍摄多张不同曝光时间的图像,并将其融合为一张包含更广泛亮度范围的图像,从而在视觉上更接近真实世界的亮度。多曝光融合是实现HDR效果的关键步骤。在这一过程中,我们需要拍摄多张不同曝光时间的图像,然后将这些图像融合为一张HDR图像。多曝光融合技术能够捕捉到更多细节,特别是在高光和阴影区域,从而使得图像在视觉上更加真实和生动。

在本文中,我将深入探讨多曝光融合技术的基本原理、常用算法以及实际应用并通过示例和代码,帮助您了解如何使用Python和OpenCV库来实现多曝光融合。

二、多曝光融合方案:

我们首先将读取的图片封装成一个列表。接着,我们根据图像内容和曝光时间来计算相机的CRF(相机响应函数),这一步骤对于后续图像融合至关重要。利用计算得到的CRF,我们将多曝光图像进行融合,以获得更丰富的图像细节。最后,通过色彩映射技术,将融合后的多曝光图片进行映射处理,使得最终生成的图片在色彩上更加饱满、自然。

三、算法实现步骤

3.1 读取图像与曝光时间:

代码如下(示例):

python 复制代码
def readImagesAndTimes():
    """
    该函数用于读取多张图像及其对应的曝光时间。

    1. 首先,定义一个曝光时间数组,其中包含四张图像的曝光时间,单位为秒。
    2. 接着,定义一个文件名列表,包含四张图像的路径。
    3. 使用一个循环遍历文件名列表,对于每个文件名,使用OpenCV的imread函数读取图像。
    4. 将读取到的图像添加到images列表中。
    5. 循环结束后,返回images列表和曝光时间数组。

    :return: images: 包含四张图像的列表。
                times: 包含四张图像曝光时间的数组。
    """
    times = np.array([1 / 30.0, 0.25, 2.5, 15.0], dtype=np.float32)  # 定义曝光时间数组
    filenames = ["F:\ccccccc/img09.jpg", "F:\ccccccc/img08.jpg", "F:\ccccccc/img04.jpg", "F:\ccccccc/img01.jpg"]  # 定义文件名列表
    images = []  # 创建一个空列表来存储图像
    for filename in filenames:  # 遍历文件名列表
        im = cv2.imread(filename)  # 使用OpenCV的imread函数读取图像
        images.append(im)  # 将读取到的图像添加到images列表中
    return images, times  # 返回images列表和曝光时间数组

3.2 计算响应曲线并合并

计算相机响应曲线(CRF)的过程可以简述如下:

首先,通过分析不同曝光时间下的图像数据,计算出相机的响应曲线,即CRF。这一步通常涉及对图像的亮度进行采样,并使用数学模型(如多项式或指数函数)来拟合这些采样点,从而得到一个能够描述相机如何将场景亮度转换为数字信号的函数。

然后,利用得到的CRF,对多张具有不同曝光时间的图像进行融合处理。这一过程包括以下步骤:

  1. 将每张图像的像素值根据CRF转换为场景亮度值。
  2. 对转换后的亮度值进行加权平均,以平衡不同曝光图像之间的亮度差异。
  3. 将融合后的亮度值重新映射回像素值,得到一张具有宽动态范围的单张图像。

代码如下(示例):

python 复制代码
# 创建一个用于计算相机响应函数(CRF)的对象
calibrateDebevec = cv2.createCalibrateDebevec()
# 使用该对象处理多张图像和对应的曝光时间,以计算CRF
responseDebevec = calibrateDebevec.process(images, times)
# 创建一个用于合并多张图像的对象
mergeDebevec = cv2.createMergeDebevec()
# 使用该对象处理多张图像、曝光时间以及计算出的CRF,以合并为一张HDR图像
hdrDebevec = mergeDebevec.process(images, times, responseDebevec)

3.3 色调映射

常见的色调映射方法有三种分别为
1. Drago色调映射:
特点 :Drago色调映射算法是基于感知的,它试图模拟人眼对亮度的适应能力。该算法特别强调在低亮度区域保持细节,同时在高亮度区域避免过曝。
参数 :通常包括一个对比度参数,用于调整图像的整体对比度。
效果 :产生的图像通常具有较好的视觉舒适度和细节保留,特别是在暗部区域。
2. Reinhard色调映射:
特点 :Reinhard色调映射算法是基于全局对比度压缩的,它通过调整图像的亮度,使得图像的亮度分布符合特定的统计特性(例如,亮度直方图的均值)。
参数 :可能包括亮度、对比度、饱和度和白色点等参数,允许用户对最终图像的外观进行精细调整。
效果 :产生的图像通常具有自然的亮度和对比度,但可能在极端亮度和暗度区域丢失一些细节。
3. Mantiuk色调映射:
特点 :Mantiuk色调映射算法强调在压缩动态范围的同时保持图像的局部对比度。它使用了一种称为"细节增强"的技术,可以在保留更多细节的同时避免晕轮效应(halos)。
参数 :通常包括对比度、饱和度和亮度参数,这些参数可以帮助用户根据需要调整图像的视觉风格。
效果:产生的图像通常具有更高的对比度和更丰富的细节,尤其是在高光和阴影区域。这种算法特别适合于需要强调场景细节和结构的场景。

python 复制代码
# 创建一个用于Drago色调映射的对象,并设置对比度参数
tonemapDrago = cv2.createTonemapDrago(1.0, 0.7)
# 使用Drago色调映射对象处理HDR图像,得到LDR图像
ldrDrago = tonemapDrago.process(hdrDebevec)
# 调整LDR图像的亮度,使其更接近标准显示设备的范围
ldrDrago = 3 * ldrDrago
# 将调整后的LDR图像保存为jpg格式
cv2.imwrite("ldr-Drago.jpg", ldrDrago * 255)
# 创建一个用于Reinhard色调映射的对象,并设置对比度参数
tonemapReinhard = cv2.createTonemapReinhard(1.5, 0, 0, 0)
# 使用Reinhard色调映射对象处理HDR图像,得到LDR图像
ldrReinhard = tonemapReinhard.process(hdrDebevec)
# 将Reinhard色调映射后的LDR图像保存为jpg格式
cv2.imwrite("ldr-Reinhard.jpg", ldrReinhard * 255)
# 创建一个用于Mantiuk色调映射的对象,并设置对比度参数
tonemapMantiuk = cv2.createTonemapMantiuk(2.2, 0.85, 1.2)
# 使用Mantiuk色调映射对象处理HDR图像,得到LDR图像
ldrMantiuk = tonemapMantiuk.process(hdrDebevec)
# 调整LDR图像的亮度,使其更接近标准显示设备的范围
ldrMantiuk = 3 * ldrMantiuk
# 将Mantiuk色调映射后的LDR图像保存为jpg格式
cv2.imwrite("ldr-Mantiuk.jpg", ldrMantiuk * 255)

四:整体代码实现

python 复制代码
import cv2
import numpy as np
def readImagesAndTimes():
    times = np.array([1 / 30.0, 0.25, 2.5, 15.0], dtype=np.float32)
    filenames = ["F:\ccccccc/img09.jpg", "F:\ccccccc/img08.jpg", "F:\ccccccc/img04.jpg", "F:\ccccccc/img01.jpg"]
    images = []
    for filename in filenames:
        im = cv2.imread(filename)
        images.append(im)

    return images, times

if __name__ == '__main__':
    # Read images and exposure times
    print("Reading images ... ")
    images, times = readImagesAndTimes()
    calibrateDebevec = cv2.createCalibrateDebevec()
    responseDebevec = calibrateDebevec.process(images, times)
    mergeDebevec = cv2.createMergeDebevec()
    hdrDebevec = mergeDebevec.process(images, times, responseDebevec)
    # Save HDR image.
    cv2.imwrite("hdrDebevec.hdr", hdrDebevec)
    print("saved hdrDebevec.jpg ")
    # # Tonemap using Drago's method to obtain 24-bit color image
    tonemapDrago = cv2.createTonemapDrago(1.0, 0.7)
    ldrDrago = tonemapDrago.process(hdrDebevec)
    ldrDrago = 3 * ldrDrago
    cv2.imwrite("ldr-Drago.jpg", ldrDrago * 255)
    # # Tonemap using Reinhard's method to obtain 24-bit color image
    tonemapReinhard = cv2.createTonemapReinhard(1.5, 0, 0, 0)
    ldrReinhard = tonemapReinhard.process(hdrDebevec)
    cv2.imwrite("ldr-Reinhard.jpg", ldrReinhard * 255)
    # # Tonemap using Mantiuk's method to obtain 24-bit color image
    tonemapMantiuk = cv2.createTonemapMantiuk(2.2, 0.85, 1.2)
    ldrMantiuk = tonemapMantiuk.process(hdrDebevec)
    ldrMantiuk = 3 * ldrMantiuk
    cv2.imwrite("ldr-Mantiuk.jpg", ldrMantiuk * 255)

五:效果

不同曝光图像:



融合后的图像:

drago:

Reinhard:

Mantiuk:

相关推荐
学习前端的小z28 分钟前
【AIGC】如何通过ChatGPT轻松制作个性化GPTs应用
人工智能·chatgpt·aigc
可均可可32 分钟前
C++之OpenCV入门到提高004:Mat 对象的使用
c++·opencv·mat·imread·imwrite
幸运超级加倍~1 小时前
软件设计师-上午题-16 算法(4-5分)
笔记·算法
yannan201903131 小时前
【算法】(Python)动态规划
python·算法·动态规划
埃菲尔铁塔_CV算法1 小时前
人工智能图像算法:开启视觉新时代的钥匙
人工智能·算法
EasyCVR1 小时前
EHOME视频平台EasyCVR视频融合平台使用OBS进行RTMP推流,WebRTC播放出现抖动、卡顿如何解决?
人工智能·算法·ffmpeg·音视频·webrtc·监控视频接入
linsa_pursuer1 小时前
快乐数算法
算法·leetcode·职场和发展
小芒果_011 小时前
P11229 [CSP-J 2024] 小木棍
c++·算法·信息学奥赛
qq_434085901 小时前
Day 52 || 739. 每日温度 、 496.下一个更大元素 I 、503.下一个更大元素II
算法
Beau_Will1 小时前
ZISUOJ 2024算法基础公选课练习一(2)
算法