【HDR图像处理】HDR图像的色调映射 | python+opencv代码实现总结

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

最近在做HDR图像的课题,这里对HDR图像处理里面的关键技术进行记录和总结

一、前提opencv知识

1.1、opencv打开一般照片并且显示

import cv2
# 读取照片
img = cv2.imread('photo.jpg')
# 显示照片
cv2.imshow('Photo', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

1.2、opencv打开HDR图像(这里先不讲如何imshow)

import cv2
# 读取照片
img = cv2.imread('photo.hdr',cv2.IMREAD_ANYDEPTH)

cv2.IMREAD_ANYDEPTH参数告诉OpenCV要读取所有像素值,包括高动态范围(HDR)像素值。

除此之外,还可这样读取HDR图像:

import cv2
# 读取照片
img = cv2.imread('photo.hdr',cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR)

以上两句话在读取HDR图像时是等价的(来自chatgpt)

一般情况下,读取了HDR图像后,需要对其进行归一化等操作(也就是映射到LDR域)。如果不进行归一化等操作,直接使用imshow可能会报错,或者图像一片白,因为HDR图像的单个像素点的亮度值非常高,早就超出了0-255的这个范围,比如如下代码:

import cv2
# 读取照片
img = cv2.imread('gt.hdr',cv2.IMREAD_UNCHANGED)
# 显示照片
cv2.imshow('Photo', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
这时候展示出的图像一片白

如果不用opencv,用一些自带色调映射的图像查看编辑器也是可以的,比如我自己用的是2345看图王,可以打开HDR,EXR等文件

二、经典的色调映射技术以及opencv代码实现

这些色调映射方法的提出时间是不同的,大致如下:

Reinhard:2001年

Drago:2003年

Durand:2005年

Mantiuk:2008年

这些方法的提出都是为了解决数字图像处理中的色调映射问题,但是它们的具体实现方式和效果略有不同。在实际应用中,可以根据需要选择适合的色调映射方法。

2.1、Reinhard

1)Reinhard

import cv2

# 读取HDR图像
src_img = cv2.imread('gt.hdr', cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR)

# 创建Reinhard色调映射对象
Reinhard = cv2.createTonemapReinhard()

# 对HDR图像进行色调映射
dst_img = Reinhard.process(src_img)

# 保存输出图像
cv2.imwrite('Reinhard.jpg', dst_img * 255)
img=cv2.imread('Reinhard.jpg')
cv2.imshow('Reinhard', img)

# 等待按键按下
cv2.waitKey(0)

# 释放窗口
cv2.destroyAllWindows()

2.2、Drago

2)Drago

import cv2

# 读取HDR图像
src_img = cv2.imread('gt.hdr', cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR)

# 创建Reinhard色调映射对象
Drago = cv2.createTonemapDrago()

# 对HDR图像进行色调映射
dst_img = Drago.process(src_img)

# 保存输出图像
cv2.imwrite('Drago.jpg', dst_img * 255)
img=cv2.imread('Drago.jpg')
cv2.imshow('Drago', img)

# 等待按键按下
cv2.waitKey(0)

# 释放窗口
cv2.destroyAllWindows()

2.3、Durand

3)Durand

import cv2

# 读取HDR图像
src_img = cv2.imread('gt.hdr', cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR)

# 创建Reinhard色调映射对象
Durand = cv2.createTonemapDurand()

# 对HDR图像进行色调映射
dst_img = Durand.process(src_img)

# 保存输出图像
cv2.imwrite('Durand.jpg', dst_img * 255)
img=cv2.imread('Durand.jpg')
cv2.imshow('Durand', img)

# 等待按键按下
cv2.waitKey(0)

# 释放窗口
cv2.destroyAllWindows()

2.4、Mantiuk

4)Mantiuk

import cv2

# 读取HDR图像
src_img = cv2.imread('gt.hdr', cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR)

# 创建Reinhard色调映射对象
Mantiuk = cv2.createTonemapMantiuk()

# 对HDR图像进行色调映射
dst_img = Mantiuk.process(src_img)
print(dst_img)

# 保存输出图像
cv2.imwrite('Mantiuk.jpg', dst_img * 255)
img=cv2.imread('Mantiuk.jpg')
cv2.imshow('Mantiuk', img)

# 等待按键按下
cv2.waitKey(0)

# 释放窗口
cv2.destroyAllWindows()

值得注意的是,使用cv2.createToneXXXX函数时,返回的是一个归一化到0-1的numpy数组,所以后续的展示imshow中需要乘上255。当然如果不乘上255也是可以显示的:虽然像素值被归一化到[0,1]的浮点数范围内,但在显示图像时,imshow函数会自动将像素值转换为[0,255]的整数,然后再进行显示。这是因为在显示图像时,需要将像素值映射到显示设备的亮度范围内,而通常情况下,显示设备的亮度范围是[0,255]的整数。因此,即使像素值已经归一化到[0,1]的浮点数范围内,imshow函数仍然可以正常显示图像。

2.5、对比

我们来看一下三种算法对比效果(Durand报错了 这里不展示):
在这里插入图片描述
从左到右依次为Reinhard Drago Mantiuk

代码如下:

import cv2
import numpy as np

# 加载HDR图像
src_img = cv2.imread('gt.hdr', cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR)
xianxing = cv2.normalize(src_img, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC3)
# 创建色调映射对象
Reinhard = cv2.createTonemapReinhard()
Drago = cv2.createTonemapDrago()
Mantiuk = cv2.createTonemapMantiuk()

# 对HDR图像进行色调映射
Reinhard_img = Reinhard.process(src_img)
Drago_img = Drago.process(src_img)
Mantiuk_img = Mantiuk.process(src_img)

# 将四幅图像拼接为2×2的矩阵
result = np.hstack((Reinhard_img, Drago_img, Mantiuk_img))


# 显示结果
cv2.imshow('Result', result)
cv2.waitKey()
cv2.destroyAllWindows()

2.6、线性映射

我们再来看看线性映射的结果(强行弄成0-255):
在这里插入图片描述
可以看出效果非常不好
代码如下,主要靠的是这句话:ldr_image = cv2.normalize(hdr_image, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC3)

import cv2

# 读取HDR图像
hdr_image = cv2.imread('gt.hdr', cv2.IMREAD_ANYDEPTH | cv2.IMREAD_COLOR )
print(hdr_image.shape)
# 转换图像格式
ldr_image = cv2.normalize(hdr_image, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC3)

# 显示图像
cv2.imshow('HDR Image', ldr_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

三.u律压缩(u律色调映射)

在目前很多的HDR图像生成的国内硕士论文里,大多提到了这种方法:
μ律本身是用于压缩音频信号动态范围的算法,但是它也可以用于压缩 HDR 图像的动态范围。μ律色调映射公式如下:
在这里插入图片描述
其中,
H 表示被归一化到 [0,1] 范围的 HDR 图像,T 表示色调映射后的图像。
这里u的取值论文里都不太一样 ,有些是500,5000

以下是chatgpt生成的代码:

import cv2
import numpy as np

def mu_law_tonemap(hdr_img, mu=5000):
    hdr_img = np.float32(hdr_img)
    L = np.log(1 + mu * hdr_img) / np.log(1 + mu)
    L = np.uint8(L * 255)
    return L

# 读取HDR图像
hdr_img = cv2.imread('gt.hdr', cv2.IMREAD_ANYDEPTH|cv2.IMREAD_COLOR)

# 进行μ律色调映射
tonemapped_img = mu_law_tonemap(hdr_img)

# 显示结果
cv2.imshow('HDR Image', hdr_img)
cv2.imshow('Tonemapped Image', tonemapped_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个使用PythonOpenCV进行图像处理的例子: 首先,确保已经安装了PySimpleGUI、cv2和numpy库文件。可以使用以下命令通过pip安装它们: ```shell pip install pysimplegui pip install opencv-python pip install numpy ``` 然后,设计GUI界面。可以使用PySimpleGUI库来实现GUI可视化。以下是一个简单的GUI设计示例: ```python import PySimpleGUI as sg # 创建GUI窗口 layout = [[sg.Image(key='image')]] window = sg.Window('Image Processing', layout, finalize=True) # 打开内置摄像头 cap = cv2.VideoCapture(0) while True: event, values = window.read(timeout=0, timeout_key='timeout') # 实时读取图像 ret, frame = cap.read() # GUI实时更新 imgbytes = cv2.imencode('.png', frame)[1].tobytes() window['image'].update(data=imgbytes) if event == sg.WINDOW_CLOSED: break window.close() ``` 这段代码创建了一个名为"Image Processing"的GUI窗口,其中包含一个用于显示图像图像框。通过打开内置摄像头,可以实时读取图像,并将其显示在GUI窗口中。当用户关闭窗口时,程序退出。 4、实时图像处理 4.1、阈值二值化 阈值二值化是一种常用的图像处理技术,可以将图像转换为黑白二值图像。以下是一个简单的阈值二值化示例: ```python # 读取图像 image = cv2.imread('image.jpg', 0) # 阈值二值化 _, binary_image = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY) # 显示结果 cv2.imshow('Binary Image', binary_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个例子中,首先使用cv2.imread()函数读取一张灰度图像。然后,使用cv2.threshold()函数将图像进行阈值二值化处理。最后,使用cv2.imshow()函数显示二值化后的图像
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值