您好,
会员登录 快速注册
退出 ( 条未读消息)
关于本站 意见反馈 首页

公告:小宅博客网可以开发票了,需要发票的,去群里找群主哈!!
全部文章分类
  • 人工智能 >

  • 编程语言 >

  • WPF系列 >

  • ASP.NET系列 >

  • Linux >

  • 数据库 >

  • 嵌入式 >

  • WEB技术 >

  • PLC系列 >

  • 微服务与框架 >

  • 小宅DIY >

  • 学习资料 >

OpenCv基础 ANN车牌识别 yolov5车牌识别 指针式仪表识别 ROS系列 YOLO Halcon Detectron2 昇腾AI ChatGPT在线体验 英伟达JETSON ChatGLM ChatTTS FunASR 地平线 ByteTrack 魔搭社区 LangChain
C C# C++ Python Java Go
WPF
ASP.NET小功能 GPS定位系统-MVC GPS定位系统-VUE ASP.NET WebRTC
Linux Linux内核 Shell MakeFile
MySql SqlServer Oracle
STM8 STM32 51单片机
VUE入门 HTML JavaScript CSS layui镜像网站 ElementUi中文官网 element-plus 图标
三菱 欧姆龙 西门子 施耐德 松下 台达
IOTSharp IOTGateway ABP FRAMEWORK Docker
亚克力音响 编程仙途:智驭万法
面试题与技巧 Python入门技能树 微软C#教程
首页 编程之美 工具下载 全国就业 流量地图 文心一言
OpenCv基础
内容介绍与资料分享 C# OpenCv环境搭建 C++ OpenCv环境搭建 Python OpenCv环境搭建 Java OpenCv环境搭建 OpenCv组件结构解析 OpenCv命名规范 OpenCv基本专业术语与方法 OpenCV 常用函数与构造体详细说明 创建画布 打开一张图片 利用imwrite生成透明png图像 图像打开、混合显示和输出 图像腐蚀 blur图像模糊(均值滤波) sobel边缘检测 canny边缘检测 Scharr滤波器 程序性能检测及优化 视频播放 摄像头录像与播放 双摄像头操作与图像相似度检测 颜色空间转换与物体追踪 彩色目标追踪 光流法运动目标检测 OpenCV中的稠密光流 背景减除 点追踪 人脸识别 支持向量机之SVM引导 支持向量机之处理线性不可分数据 ROI矩形截取 鼠标绘制矩形 用OpenCV进行基本绘图 绘图函数(python中文显示) 把鼠标当画笔 用滑动条做调色板 图像的基础操作 图像上的算术运算 多通道图像混合 图像的亮度、对比度调整 XML和YAML文件的写入 XML和YAML文件的读取 卷积操作 三种线性滤波 两种非线性滤波 7种图像处理形态学(1) 7种图像处理形态学(2) 漫水填充 图像缩放与图像金字塔 二值化基本阈值操作 图像阈值 Laplacian图像变换(拉普拉斯算子) 霍夫变换HoughLines边缘检测与线性矢量 霍夫变换HoughLinesP边缘检测与线性矢量 霍夫变换HoughCircles边缘检测与线性矢量 LSD快速直线检测 几何变换 remap重映射 remap实现多种重映射 仿射变换综合示例 直方图均衡化 CLAHE有限对比适应性直方图均衡化 draw最大的轮廓 轮廓的性质 点到多边形的最短距离 形状匹配 椭圆拟合与直线拟合 基础轮廓查找 查找并绘制轮廓综合示例 凸缺陷/凸包检测 凸包检测 创建包围轮廓的矩形边界 创建包围轮廓的圆形边 创建包围轮廓的矩形和圆形边界框 查找和绘制图片轮廓矩 分水岭算法 图像修补 H-S二维直方图的绘制/2D直方图 一维直方图的绘制 RGB三色直方图的绘制 直方图对比 使用掩膜绘制直方图 直方图反向投影 模板匹配 多对象模板匹配 cornerHarris角点检测 cornerHarris角点检测综合示例 Shi-Tomasi角点检测 亚像素级角点检测 角点检测的FAST算法(FAST特征检测器) 颜色识别 warpPerspective透视变换 SURF/SIFT特征点检测 SURF/SIFT特征描述 使用FLANN进行特征点匹配 FLANN结合SURF/SIFT进行关键点的描述和匹配 寻找已知物体(一) 寻找已知物体(二) 目标查找与跟踪 - Meanshift与CamShift BRIEF描述符 ORB ORB算法描述与匹配 LUT 图像灰度调整 离散傅里叶变换 双目摄像头与图像拼接 环境亮度检测 stitching 全景拼接 Maze-Solver迷宫解密 使用Haar分类器之面部检测 使用Haar分类器之行人检测 OpenCv Haar/LBP/HOG分类器-人脸识别 斑点检测 使用GrabCut算法进行交互式前景提取 对极几何 摄像机标定 姿势估计 立体图像中的深度地图 OpenCv中的KNN KNN手写数字识别 ​SVM手写数字识别(使用SVM进行手写数据OCR) 英文字母的OCR 预测手写数字(预测不准) K值聚类(一) K值聚类(二) 计算摄影学-图像去噪 高动态范围成像(HDRI或HDR) MSER区域检测 二维码、条形码识别 删除图像中的水印 OpenCv深度学习dnn Kinect-深度相机 OpenCv常用数学算法 360度旋转直线绘制 向量延长线上的像素扫描 Tools工具包-窗体分配
计算摄影学-图像去噪
MSER区域检测
激萌の小宅 小宅博客 OpenCv基础

文章作者:激萌の小宅

促销:¥0

价格:¥0

配送方式: 购买后立即生效(如购买异常,请联系站长)
付款之后一定要等待自动跳转结束,否则购买可能会失败
  • 0 天

    有效期

  • 0

    总销量

  • 0

    累计评价

高动态范围成像(HDRI或HDR)

当前功能貌似是原PDF作者自行扩展的内容,不在PDF文档中,博主这里也顺便整理一下。

当前系列所有demo下载地址:

https://github.com/GaoRenBao/OpenCv4-Demo

https://gitee.com/fuckgrb/OpenCv4-Demo

不同编程语言对应的OpenCv版本以及开发环境信息如下: 

语言

OpenCv版本

IDE

C#

OpenCvSharp4.4.8.0.20230708

Visual Studio 2022

C++

OpenCv-4.5.5-vc14_vc15

Visual Studio 2022

Python

OpenCv-Python (3.4.2.16)

PyCharm Community Edition 2022.1.3


注意:

 1、createTonemapDurand被作者生气专利了,高版本python无法使用该函数,目前测试opencv-python 3.4.2.16版本可以使用。

离线安装包下载地址:

https://pypi.tuna.tsinghua.edu.cn/simple/opencv-python/

https://pypi.tuna.tsinghua.edu.cn/simple/opencv-contrib-python/

QQ截图20231207145311.jpg


然后安装命令:

pip install numpy==1.14.5 -i https://mirror.baidu.com/pypi/simple
pip install opencv_python-3.4.2.16-cp37-cp37m-win_amd64.whl opencv_contrib_python-3.4.2.16-cp37-cp37m-win_amd64.whl


2、C#的opencv4版本缺了好多方法。。。


官方教程:

http://docs.opencv.org/3.2.0/d2/df0/tutorial_py_hdr.html


1、了解如何从曝光序列生成和显示HDR图像。

2、使用曝光融合合并曝光序列。


        高动态范围成像(HDRI或HDR)是一种用于成像和摄影的技术,可以重现比标准数字成像或摄影技术更大的动态光度范围。虽然人眼可以调整到广泛的光线条件,但大多数成像设备每通道使用8位,因此我们仅限于256级。当我们拍摄现实世界的场景时,明亮的地区可能曝光过度,而黑暗的区域可能曝光不足,所以我们无法使用单次曝光拍摄所有细节。HDR图像与每个通道使用超过8位(通常为32位浮点值)的图像一起使用,允许更宽的动态范围。

        有不同的获取HDR图像的方法,但最常见的是使用不同曝光值拍摄的场景的照片。要组合这些曝光,了解您的相机的响应功能是有用的,并且有算法来估计它。合并HDR图像后,必须将其转换回8位才能在通常的显示屏上进行查看。这个过程叫做tonemapping。当场景或相机的对象在拍摄之间移动时,会出现附加的复杂性,因为具有不同曝光的图像应该被注册和对齐。

        在本教程中,我们展示了两种算法(Debvec,Robertson)从曝光序列生成和显示HDR图像,并展示了一种称为曝光融合(Mertens)的替代方法,它产生低动态范围图像,不需要曝光时间数据。此外,我们估计对于许多计算机视觉算法具有重要价值的相机响应函数(CRF)。HDR管道的每一步都可以使用不同的算法和参数来实现,因此请参考参考手册来查看。


测试原图如下:

从左到右:1tl.jpg、2tr.jpg

1tl.jpg 2tr.jpg

从左到右:3bl.jpg、4br.jpg

3bl.jpg 4br.jpg


C#版本代码如下:

参考博客:https://blog.csdn.net/jimtien/article/details/119026930

QQ截图20231207160228.jpg

代码如下:

using OpenCvSharp;
using OpenCvSharp.XPhoto;
using System.Collections.Generic;

namespace demo
{
    internal class Program
    {

        static void Main(string[] args)
        {
            List<Mat> images = new List<Mat>()
            {
                Cv2.ImRead("../../../images/tbs/1tl.jpg"),
                Cv2.ImRead("../../../images/tbs/2tr.jpg"),
                Cv2.ImRead("../../../images/tbs/3bl.jpg"),
                Cv2.ImRead("../../../images/tbs/4br.jpg"),
            };
            float[] exposures = new float[] { 15.0f, 2.5f, 0.25f, 0.0333f };

            // 估计相机响应
            Mat response = new Mat();
            CalibrateDebevec calibrate = CalibrateDebevec.Create();
            calibrate.Process(images, response, exposures);

            // 生成HDR图片
            Mat hdr = new Mat();
            MergeDebevec merge_debevec = MergeDebevec.Create();
            merge_debevec.Process(images, hdr, exposures, response);

            /* 找不到 createMergeRobertson 的对应方法 */

            // Tonemap
            Mat ldr = new Mat();
            TonemapDurand tonemap = TonemapDurand.Create(0.5f);
            tonemap.Process(hdr, ldr);

            // Exposure fusion using Mertens
            // 这里我们展示了一种可以合并曝光图像的替代算法
            Mat fusion = new Mat();
            MergeMertens merge_mertens = MergeMertens.Create();
            merge_mertens.Process(images, fusion);

            Cv2.ImShow("fusion.png", fusion);
            Cv2.ImShow("ldr.png", ldr);
            Cv2.ImShow("hdr.hdr", hdr);
            Cv2.WaitKey(0);
        }
    }
}


C++版本代码如下:

C++版本也没有 createTonemapDurand 方法,我这里用 createTonemapDrago 代替了

效果如下:

QQ截图20231207155507.jpg

代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/photo.hpp"

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    vector<Mat> img_list;
    img_list.push_back(imread("../images/tbs/1tl.jpg"));
    img_list.push_back(imread("../images/tbs/2tr.jpg"));
    img_list.push_back(imread("../images/tbs/3bl.jpg"));
    img_list.push_back(imread("../images/tbs/4br.jpg"));

    vector<float> exposure_times = { 15.0f, 2.5f, 0.25f, 0.0333f };

    Mat hdr_debvec, hdr_robertson;
    Ptr<MergeDebevec> merge_debvec = createMergeDebevec(); 
    merge_debvec->process(img_list, hdr_debvec, exposure_times);
    Ptr<MergeRobertson> merge_robertson = createMergeRobertson();
    merge_robertson->process(img_list, hdr_robertson, exposure_times);

    // Tonemap HDR image
    // 没有 createTonemapDurand 方法,只能用 createTonemapDrago 代替了
    Mat res_debvec;
    Ptr<TonemapDrago> tonemap1 = createTonemapDrago(2.2);
    tonemap1->process(hdr_debvec, res_debvec);

    Mat res_robertson;
    Ptr<TonemapDrago> tonemap2 = createTonemapDrago(1.3);
    tonemap2->process(hdr_robertson, res_robertson);

    // Exposure fusion using Mertens
    Mat res_mertens;
    Ptr<MergeMertens> merge_mertens = createMergeMertens();
    merge_mertens->process(img_list, res_mertens);

    imshow("ldr_debvec.jpg", res_debvec);
    imshow("ldr_robertson.jpg", res_robertson);
    imshow("fusion_mertens.jpg", res_mertens);
    waitKey(0);

    return 0;
}


Python版本代码如下:

python包版本说明:

微信截图_20231207144617.jpg

运行效果:

QQ截图20231207150357.jpg

测试代码如下:

import cv2
import numpy as np
from re import match

# 通过这个代码,可以查看opencv中是否包含createTonemapDurand
cv2_filtered = filter(lambda v: match('.*Tonemap', v), dir(cv2))
[print(val) for val in cv2_filtered]

# 第一阶段只是将所有图像加载到列表中。此外,我们将需要常规HDR算法的曝光时间。注意数据类型,因为图像应为1通道或3通道8位(np.uint8),曝光时间需要为float32,以秒为单位。
# Loading exposure images into a list
img_fn = ["../images/tbs/1tl.jpg", "../images/tbs/2tr.jpg", "../images/tbs/3bl.jpg", "../images/tbs/4br.jpg"]
img_list = [cv2.imread(fn) for fn in img_fn]
exposure_times = np.array([15.0, 2.5, 0.25, 0.0333], dtype=np.float32)

# Merge exposures to HDR image
# 在这个阶段,我们将曝光序列合并成一个HDR图像,显示了我们在OpenCV中的两种可能性。第一种方法是Debvec,第二种是Robertson。请注意,HDR图像的类型为float32,而不是uint8,因为它包含所有曝光图像的完整动态范围。

merge_debvec = cv2.createMergeDebevec()
hdr_debvec = merge_debvec.process(img_list, times=exposure_times.copy())
merge_robertson = cv2.createMergeRobertson()
hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy())

# Tonemap HDR image
# 我们将32位浮点HDR数据映射到范围[0..1]。实际上,在某些情况下,值可能大于1或低于0,所以注意我们以后不得不剪切数据,以避免溢出。
tonemap1 = cv2.createTonemapDurand(gamma=2.2)
res_debvec = tonemap1.process(hdr_debvec.copy())
tonemap2 = cv2.createTonemapDurand(gamma=1.3)
res_robertson = tonemap2.process(hdr_robertson.copy())

# Exposure fusion using Mertens
# 这里我们展示了一种可以合并曝光图像的替代算法,我们不需要曝光时间。我们也不需要使用任何tonemap算法,因为Mertens算法已经给出了[0..1]范围内的结果。
merge_mertens = cv2.createMergeMertens()
res_mertens = merge_mertens.process(img_list)

# Convert datatype to 8-bit and save
# 为了保存或显示结果,我们需要将数据转换为[0..255]范围内的8位整数。
res_debvec_8bit = np.clip(res_debvec * 255, 0, 255).astype('uint8')
res_robertson_8bit = np.clip(res_robertson * 255, 0, 255).astype('uint8')
res_mertens_8bit = np.clip(res_mertens * 255, 0, 255).astype('uint8')

cv2.imshow("ldr_debvec.jpg", res_debvec_8bit)
cv2.imshow("ldr_robertson.jpg", res_robertson_8bit)
cv2.imshow("fusion_mertens.jpg", res_mertens_8bit)
cv2.waitKey()
exit(0)

# Estimate camera response function (CRF)
# 相机响应功能(CRF)给出了场景辐射度与测量强度值之间的连接。如果在一些计算机视觉算法中非常重要,包括HDR算法,CRF。这里我们估计反相机响应函数并将其用于HDR合并。
cal_debvec = cv2.createCalibrateDebevec()
crf_debvec = cal_debvec.process(img_list, times=exposure_times)
hdr_debvec = merge_debvec.process(img_list, times=exposure_times.copy(), response=crf_debvec.copy())
cal_robertson = cv2.createCalibrateRobertson()
crf_robertson = cal_robertson.process(img_list, times=exposure_times)
hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy(), response=crf_robertson.copy())


计算摄影学-图像去噪
MSER区域检测

友情链接: CSDN激萌の小宅 95知识库 自考题库 罗分明个人网络博客 精益编程leanboot

小宅博客  www.bilibili996.com All Rights Reserved. 备案号: 闽ICP备2024034575号

网站经营许可证  福建省福州市 Copyright©2021-2025 版权所有

小宅博客
首页 智能家居 地图定位
公告:小宅博客网可以开发票了,需要发票的,去群里找群主哈!!

文章作者:激萌の小宅

促销:¥0

价格:¥0

配送方式: 购买后立即生效(如购买异常,请联系站长)
付款之后一定要等待自动跳转结束,否则购买可能会失败
  • 0 天

    有效期

  • 0

    总销量

  • 0

    累计评价

高动态范围成像(HDRI或HDR)

当前功能貌似是原PDF作者自行扩展的内容,不在PDF文档中,博主这里也顺便整理一下。

当前系列所有demo下载地址:

https://github.com/GaoRenBao/OpenCv4-Demo

https://gitee.com/fuckgrb/OpenCv4-Demo

不同编程语言对应的OpenCv版本以及开发环境信息如下: 

语言

OpenCv版本

IDE

C#

OpenCvSharp4.4.8.0.20230708

Visual Studio 2022

C++

OpenCv-4.5.5-vc14_vc15

Visual Studio 2022

Python

OpenCv-Python (3.4.2.16)

PyCharm Community Edition 2022.1.3


注意:

 1、createTonemapDurand被作者生气专利了,高版本python无法使用该函数,目前测试opencv-python 3.4.2.16版本可以使用。

离线安装包下载地址:

https://pypi.tuna.tsinghua.edu.cn/simple/opencv-python/

https://pypi.tuna.tsinghua.edu.cn/simple/opencv-contrib-python/

QQ截图20231207145311.jpg


然后安装命令:

pip install numpy==1.14.5 -i https://mirror.baidu.com/pypi/simple
pip install opencv_python-3.4.2.16-cp37-cp37m-win_amd64.whl opencv_contrib_python-3.4.2.16-cp37-cp37m-win_amd64.whl


2、C#的opencv4版本缺了好多方法。。。


官方教程:

http://docs.opencv.org/3.2.0/d2/df0/tutorial_py_hdr.html


1、了解如何从曝光序列生成和显示HDR图像。

2、使用曝光融合合并曝光序列。


        高动态范围成像(HDRI或HDR)是一种用于成像和摄影的技术,可以重现比标准数字成像或摄影技术更大的动态光度范围。虽然人眼可以调整到广泛的光线条件,但大多数成像设备每通道使用8位,因此我们仅限于256级。当我们拍摄现实世界的场景时,明亮的地区可能曝光过度,而黑暗的区域可能曝光不足,所以我们无法使用单次曝光拍摄所有细节。HDR图像与每个通道使用超过8位(通常为32位浮点值)的图像一起使用,允许更宽的动态范围。

        有不同的获取HDR图像的方法,但最常见的是使用不同曝光值拍摄的场景的照片。要组合这些曝光,了解您的相机的响应功能是有用的,并且有算法来估计它。合并HDR图像后,必须将其转换回8位才能在通常的显示屏上进行查看。这个过程叫做tonemapping。当场景或相机的对象在拍摄之间移动时,会出现附加的复杂性,因为具有不同曝光的图像应该被注册和对齐。

        在本教程中,我们展示了两种算法(Debvec,Robertson)从曝光序列生成和显示HDR图像,并展示了一种称为曝光融合(Mertens)的替代方法,它产生低动态范围图像,不需要曝光时间数据。此外,我们估计对于许多计算机视觉算法具有重要价值的相机响应函数(CRF)。HDR管道的每一步都可以使用不同的算法和参数来实现,因此请参考参考手册来查看。


测试原图如下:

从左到右:1tl.jpg、2tr.jpg

1tl.jpg 2tr.jpg

从左到右:3bl.jpg、4br.jpg

3bl.jpg 4br.jpg


C#版本代码如下:

参考博客:https://blog.csdn.net/jimtien/article/details/119026930

QQ截图20231207160228.jpg

代码如下:

using OpenCvSharp;
using OpenCvSharp.XPhoto;
using System.Collections.Generic;

namespace demo
{
    internal class Program
    {

        static void Main(string[] args)
        {
            List<Mat> images = new List<Mat>()
            {
                Cv2.ImRead("../../../images/tbs/1tl.jpg"),
                Cv2.ImRead("../../../images/tbs/2tr.jpg"),
                Cv2.ImRead("../../../images/tbs/3bl.jpg"),
                Cv2.ImRead("../../../images/tbs/4br.jpg"),
            };
            float[] exposures = new float[] { 15.0f, 2.5f, 0.25f, 0.0333f };

            // 估计相机响应
            Mat response = new Mat();
            CalibrateDebevec calibrate = CalibrateDebevec.Create();
            calibrate.Process(images, response, exposures);

            // 生成HDR图片
            Mat hdr = new Mat();
            MergeDebevec merge_debevec = MergeDebevec.Create();
            merge_debevec.Process(images, hdr, exposures, response);

            /* 找不到 createMergeRobertson 的对应方法 */

            // Tonemap
            Mat ldr = new Mat();
            TonemapDurand tonemap = TonemapDurand.Create(0.5f);
            tonemap.Process(hdr, ldr);

            // Exposure fusion using Mertens
            // 这里我们展示了一种可以合并曝光图像的替代算法
            Mat fusion = new Mat();
            MergeMertens merge_mertens = MergeMertens.Create();
            merge_mertens.Process(images, fusion);

            Cv2.ImShow("fusion.png", fusion);
            Cv2.ImShow("ldr.png", ldr);
            Cv2.ImShow("hdr.hdr", hdr);
            Cv2.WaitKey(0);
        }
    }
}


C++版本代码如下:

C++版本也没有 createTonemapDurand 方法,我这里用 createTonemapDrago 代替了

效果如下:

QQ截图20231207155507.jpg

代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/photo.hpp"

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
    vector<Mat> img_list;
    img_list.push_back(imread("../images/tbs/1tl.jpg"));
    img_list.push_back(imread("../images/tbs/2tr.jpg"));
    img_list.push_back(imread("../images/tbs/3bl.jpg"));
    img_list.push_back(imread("../images/tbs/4br.jpg"));

    vector<float> exposure_times = { 15.0f, 2.5f, 0.25f, 0.0333f };

    Mat hdr_debvec, hdr_robertson;
    Ptr<MergeDebevec> merge_debvec = createMergeDebevec(); 
    merge_debvec->process(img_list, hdr_debvec, exposure_times);
    Ptr<MergeRobertson> merge_robertson = createMergeRobertson();
    merge_robertson->process(img_list, hdr_robertson, exposure_times);

    // Tonemap HDR image
    // 没有 createTonemapDurand 方法,只能用 createTonemapDrago 代替了
    Mat res_debvec;
    Ptr<TonemapDrago> tonemap1 = createTonemapDrago(2.2);
    tonemap1->process(hdr_debvec, res_debvec);

    Mat res_robertson;
    Ptr<TonemapDrago> tonemap2 = createTonemapDrago(1.3);
    tonemap2->process(hdr_robertson, res_robertson);

    // Exposure fusion using Mertens
    Mat res_mertens;
    Ptr<MergeMertens> merge_mertens = createMergeMertens();
    merge_mertens->process(img_list, res_mertens);

    imshow("ldr_debvec.jpg", res_debvec);
    imshow("ldr_robertson.jpg", res_robertson);
    imshow("fusion_mertens.jpg", res_mertens);
    waitKey(0);

    return 0;
}


Python版本代码如下:

python包版本说明:

微信截图_20231207144617.jpg

运行效果:

QQ截图20231207150357.jpg

测试代码如下:

import cv2
import numpy as np
from re import match

# 通过这个代码,可以查看opencv中是否包含createTonemapDurand
cv2_filtered = filter(lambda v: match('.*Tonemap', v), dir(cv2))
[print(val) for val in cv2_filtered]

# 第一阶段只是将所有图像加载到列表中。此外,我们将需要常规HDR算法的曝光时间。注意数据类型,因为图像应为1通道或3通道8位(np.uint8),曝光时间需要为float32,以秒为单位。
# Loading exposure images into a list
img_fn = ["../images/tbs/1tl.jpg", "../images/tbs/2tr.jpg", "../images/tbs/3bl.jpg", "../images/tbs/4br.jpg"]
img_list = [cv2.imread(fn) for fn in img_fn]
exposure_times = np.array([15.0, 2.5, 0.25, 0.0333], dtype=np.float32)

# Merge exposures to HDR image
# 在这个阶段,我们将曝光序列合并成一个HDR图像,显示了我们在OpenCV中的两种可能性。第一种方法是Debvec,第二种是Robertson。请注意,HDR图像的类型为float32,而不是uint8,因为它包含所有曝光图像的完整动态范围。

merge_debvec = cv2.createMergeDebevec()
hdr_debvec = merge_debvec.process(img_list, times=exposure_times.copy())
merge_robertson = cv2.createMergeRobertson()
hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy())

# Tonemap HDR image
# 我们将32位浮点HDR数据映射到范围[0..1]。实际上,在某些情况下,值可能大于1或低于0,所以注意我们以后不得不剪切数据,以避免溢出。
tonemap1 = cv2.createTonemapDurand(gamma=2.2)
res_debvec = tonemap1.process(hdr_debvec.copy())
tonemap2 = cv2.createTonemapDurand(gamma=1.3)
res_robertson = tonemap2.process(hdr_robertson.copy())

# Exposure fusion using Mertens
# 这里我们展示了一种可以合并曝光图像的替代算法,我们不需要曝光时间。我们也不需要使用任何tonemap算法,因为Mertens算法已经给出了[0..1]范围内的结果。
merge_mertens = cv2.createMergeMertens()
res_mertens = merge_mertens.process(img_list)

# Convert datatype to 8-bit and save
# 为了保存或显示结果,我们需要将数据转换为[0..255]范围内的8位整数。
res_debvec_8bit = np.clip(res_debvec * 255, 0, 255).astype('uint8')
res_robertson_8bit = np.clip(res_robertson * 255, 0, 255).astype('uint8')
res_mertens_8bit = np.clip(res_mertens * 255, 0, 255).astype('uint8')

cv2.imshow("ldr_debvec.jpg", res_debvec_8bit)
cv2.imshow("ldr_robertson.jpg", res_robertson_8bit)
cv2.imshow("fusion_mertens.jpg", res_mertens_8bit)
cv2.waitKey()
exit(0)

# Estimate camera response function (CRF)
# 相机响应功能(CRF)给出了场景辐射度与测量强度值之间的连接。如果在一些计算机视觉算法中非常重要,包括HDR算法,CRF。这里我们估计反相机响应函数并将其用于HDR合并。
cal_debvec = cv2.createCalibrateDebevec()
crf_debvec = cal_debvec.process(img_list, times=exposure_times)
hdr_debvec = merge_debvec.process(img_list, times=exposure_times.copy(), response=crf_debvec.copy())
cal_robertson = cv2.createCalibrateRobertson()
crf_robertson = cal_robertson.process(img_list, times=exposure_times)
hdr_robertson = merge_robertson.process(img_list, times=exposure_times.copy(), response=crf_robertson.copy())