opencv-python图像增强四:多曝光融合(方法一)
文章目录
- 一、简介:
- 二、多曝光融合方案:
- 三、算法实现步骤
- 3.1 读取图像与曝光时间:
- 3.2 计算响应曲线并合并
- 3.3 色调映射
- 四:整体代码实现
- 五:效果
一、简介:
在摄影和计算机视觉领域,高动态范围(HDR)技术已经成为了捕捉丰富细节和真实感图像的重要手段。然而,要实现高质量的HDR效果,我们需要对多张不同曝光时间的图像进行融合处理。本文将探讨多曝光融合技术的基本原理和应用,帮助您深入了解这一技术如何捕捉更丰富、更真实的世界。
在自然界中,我们的眼睛能够感知从最暗到最亮的广阔亮度范围。然而,传统的相机传感器和显示设备却无法捕捉到这一完整的亮度范围,导致图像在亮度上出现失真。为了解决这一问题,HDR技术应运而生。HDR技术通过拍摄多张不同曝光时间的图像,并将其融合为一张包含更广泛亮度范围的图像,从而在视觉上更接近真实世界的亮度。多曝光融合是实现HDR效果的关键步骤。在这一过程中,我们需要拍摄多张不同曝光时间的图像,然后将这些图像融合为一张HDR图像。多曝光融合技术能够捕捉到更多细节,特别是在高光和阴影区域,从而使得图像在视觉上更加真实和生动。
在本文中,我将深入探讨多曝光融合技术的基本原理、常用算法以及实际应用并通过示例和代码,帮助您了解如何使用Python和OpenCV库来实现多曝光融合。
二、多曝光融合方案:
我们首先将读取的图片封装成一个列表。接着,我们根据图像内容和曝光时间来计算相机的CRF(相机响应函数),这一步骤对于后续图像融合至关重要。利用计算得到的CRF,我们将多曝光图像进行融合,以获得更丰富的图像细节。最后,通过色彩映射技术,将融合后的多曝光图片进行映射处理,使得最终生成的图片在色彩上更加饱满、自然。
三、算法实现步骤
3.1 读取图像与曝光时间:
代码如下(示例):
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,对多张具有不同曝光时间的图像进行融合处理。这一过程包括以下步骤:
- 将每张图像的像素值根据CRF转换为场景亮度值。
- 对转换后的亮度值进行加权平均,以平衡不同曝光图像之间的亮度差异。
- 将融合后的亮度值重新映射回像素值,得到一张具有宽动态范围的单张图像。
代码如下(示例):
# 创建一个用于计算相机响应函数(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)。
参数:通常包括对比度、饱和度和亮度参数,这些参数可以帮助用户根据需要调整图像的视觉风格。
效果:产生的图像通常具有更高的对比度和更丰富的细节,尤其是在高光和阴影区域。这种算法特别适合于需要强调场景细节和结构的场景。
# 创建一个用于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)
四:整体代码实现
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, timesif __name__ == '__main__':# Read images and exposure timesprint("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 imagetonemapDrago = cv2.createTonemapDrago(1.0, 0.7)ldrDrago = tonemapDrago.process(hdrDebevec)ldrDrago = 3 * ldrDragocv2.imwrite("ldr-Drago.jpg", ldrDrago * 255)# # Tonemap using Reinhard's method to obtain 24-bit color imagetonemapReinhard = 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 imagetonemapMantiuk = cv2.createTonemapMantiuk(2.2, 0.85, 1.2)ldrMantiuk = tonemapMantiuk.process(hdrDebevec)ldrMantiuk = 3 * ldrMantiukcv2.imwrite("ldr-Mantiuk.jpg", ldrMantiuk * 255)
五:效果
不同曝光图像:
融合后的图像:
drago:
Reinhard:
Mantiuk:
相关文章:

opencv-python图像增强四:多曝光融合(方法一)
文章目录 一、简介:二、多曝光融合方案:三、算法实现步骤3.1 读取图像与曝光时间:3.2 计算响应曲线并合并3.3 色调映射 四:整体代码实现五:效果 一、简介: 在摄影和计算机视觉领域,高动态范围&…...

Qt 实战(9)窗体 | 9.2、QDialog
文章目录 一、QDialog1、基本概念2、常用特性2.1、模态与非模态2.2、数据交互 3、总结 前言: Qt框架中的QDialog类是一个功能强大且灵活的对话框控件,广泛应用于各种GUI(图形用户界面)应用程序中,用于处理用户输入、消…...
Spring 事务机制
1. 引言 1.1 什么是事务 事务是由用户定义的一系列操作序列所组成的最小工作单元;这些操作要么全部完成,要么全部不完成,是一个不可分割的工作单元。常见于数据库中的并发控制和数据一致性处理场景。 1.2 事务的特性 事务具有以下特性&am…...

Android 13 GMS 内置壁纸
如图,原生系统上,设备上的壁纸 显示系统内置壁纸。如果没有添加内置壁纸,就显示默认的壁纸。点击进去就是预览页面 扩展下,默认壁纸在 frameworks/base/core/res/res/drawable-sw720dp-nodpi/default_wallpaper.png frameworks/b…...
【LeetCode】234. 回文链表
回文链表 题目描述: 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true示例 2&#…...

零基础学会机器学习,到底要多久?
这两天啊,有不少朋友和我说,想学机器学习,但是之前没有基础,不知道能不能学得会。 首先说结论,只要坚持,就能学会,但是一定不能三天打鱼两天晒网,要持之以恒,至少每隔两…...

视频汇聚/安防监控综合平台EasyCVR接入海康私有协议EHOME显示失败是什么原因?
安防监控/视频综合管理平台/视频集中存储/磁盘阵列EasyCVR视频汇聚平台,支持多种视频格式和编码方式(H.264/H.265),能够轻松对接各类前端监控设备,实现视频流的统一接入与集中管理。安防监控EasyCVR平台支持多种流媒体…...
Qt解析XML
背景 本来想解析VS的项目配置文件(*.vcxproj),配合cppclean来发现多余的#incldue。 结果发现低估了难度,VS会间接引入许多目录。 略有不甘,暂且作为一个解析XML文件的示例。 代码 VSProjectParser.h #include <QVector> #include…...

PwnLab: init-文件包含、shell反弹、提权--靶机渗透思路讲解
Vulnhub靶机链接回【PwnLab】 首页有一个登录框 image-20240807124822770 他没有验证码,我们试试暴力破解 image-20240807122743025 开始爆破了,全部失败,哈哈哈 image-20240807122851001 nmap全端口扫描试试 image-20240807131408315 有…...

OpenCV—二值化Threshold()、adaptiveThreshold()
cv2.threshold() c:double cv::threshold ( InputArray src, OutputArray dst, double thresh, double maxval, int type ) (注:源图片, 目标图, 阈值, 填充色, 阈值类型) python:cv.threshold(src,thresh, maxval, type[, dst]) src:源图片…...
第二天:java面向对象编程(OOP)
第二天:java面向对象编程(OOP) 1. 深入理解OOP四大特性 封装(Encapsulation):学习如何将数据(属性)和操作数据的方法(行为)组合成一个独立的单元࿰…...

Selenium + Python 自动化测试07(滑块的操作方法)
我们的目标是:按照这一套资料学习下来,大家可以独立完成自动化测试的任务。 本篇文章主要讲述如何操作滑块。 目前很多系统登录或者注册的页面都有滑块相关的验证,selenium 中对滑块的基本操作采用了元素的拖曳的方式。需要用到Actiochains模…...

三防平板满足多样化定制为工业领域打造硬件解决方案
在当今工业领域,数字化、智能化的发展趋势日益显著,对于高效、可靠且适应各种复杂环境的硬件设备需求不断增长。三防平板作为一种具有坚固耐用、防水防尘防摔特性的工业级设备,正以其出色的性能和多样化的定制能力,为不同行业的应…...

pytorch,用lenet5识别cifar10数据集(训练+测试+单张图片识别)
目录 LeNet-5 LeNet-5 结构 CIFAR-10 pytorch实现 lenet模型 训练模型 1.导入数据 2.训练模型 3.测试模型 测试单张图片 代码 运行结果 LeNet-5 LeNet-5 是由 Yann LeCun 等人在 1998 年提出的一种经典卷积神经网络(CNN)模型,主要…...
Word卡顿的处理方法
1. 检查和关闭后台程序 关闭不必要的后台程序,释放系统资源。使用任务管理器(Ctrl + Shift + Esc)查看占用CPU和内存较高的应用,并关闭它们。2. 更新Microsoft Office 确保你的Microsoft Office软件是最新版本。新版本通常修复了已知的性能问题。打开Word,点击文件 > 账…...
在 Linux上常见的10大压缩格式解压命令和它们对应的压缩格式
文章目录 前言一、解压 .zip 文件二、解压 .tar.gz 或 .tgz 文件三、解压 .tar 文件四、解压 .tar.bz2 文件五、解压 .tar.xz 文件六、解压 .gz 文件七、解压 .bz2 文件八、解压 .xz 文件九、解压 .7z 文件十、解压 .rar 文件总结 前言 Linux 命令可以解压不同格式的压缩文件。…...

【数据结构】三、栈和队列:6.链队列、双端队列、队列的应用(树的层次遍历、广度优先BFS、先来先服务FCFS)
文章目录 2.链队列2.1初始化(带头结点)不带头结点 2.2入队(带头结点)2.3出队(带头结点)❗2.4链队列c实例 3.双端队列考点:输出序列合法性栈双端队列 队列的应用1.树的层次遍历2.图的广度优先遍历3.操作系统…...

技术速递|使用 Native Library Interop 为 .NET MAUI 创建绑定
作者:Rachel Kang 排版:Alan Wang 在当今的应用开发领域,通过利用本机功能来扩展 .NET 应用程序的能力非常宝贵。.NET MAUI 处理程序架构使开发人员能够使用 .NET 代码直接操作本机控件,甚至允许无缝创建跨平台自定义控件。然而&a…...

Linux笔记 --- 标准IO
系统IO的最大特点一个是更具通用性,不管是普通文件、管道文件、设备节点文件、接字文件等等都可以使用,另一个是他的简约性,对文件内数据的读写在任何情况下都是带任何格式的,而且数据的读写也都没有经过任何缓冲处理,…...
洛谷:B3625 迷宫寻路
迷宫寻路 题目描述 机器猫被困在一个矩形迷宫里。 迷宫可以视为一个 n m n\times m nm 矩阵,每个位置要么是空地,要么是墙。机器猫只能从一个空地走到其上、下、左、右的空地。 机器猫初始时位于 ( 1 , 1 ) (1, 1) (1,1) 的位置,问能否…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...

医疗AI模型可解释性编程研究:基于SHAP、LIME与Anchor
1 医疗树模型与可解释人工智能基础 医疗领域的人工智能应用正迅速从理论研究转向临床实践,在这一过程中,模型可解释性已成为确保AI系统被医疗专业人员接受和信任的关键因素。基于树模型的集成算法(如RandomForest、XGBoost、LightGBM)因其卓越的预测性能和相对良好的解释性…...