【MATLAB Image Processing Toolbox 入门教程五】
- 1 hdrread函数
- 2 hdrwrite函数
- 3 makehdr函数
- 4 tonemap函数
- 5 tonemapfarbman函数
- 6 localtonemap函数
- 7 blendexposure函数
高动态范围(High Dynamic Range HDR)图像尽可能显示真实的场景,包含的细节程度相当高,接近于人眼的视觉范围,超出一般计算机显示器的显示范围。
本章将针对HDR的读取、创建和写入,详细介绍几个相关的函数。
1 hdrread函数
1.1 hdrread函数用法讲解
hdrread函数的用法是:
hdr=hdrread(filename) 从指定的文件filename中读取高动态范围图像
返回的hdr是一个m×n×3的数字数组。
1.2 hdrread函数用法示例
在此示例中,我们先将高动态范围图像读入工作区,并将其显示出来。
hdr=hdrread('office.hdr');
rgb=tonemap(hdr);
imshow(rgb);
上图就是高动态范围HDR图像,不过我们需要注意,在显示HDR之前,我们使用了tonemap函数对读入的office.hdr图像进行了处理,这一步的作用是将hdr图像转为适合显示的低动态范围。tonemap函数的具体使用会在第四节进行详细讲解。如果不用tonemap函数,直接显示hdr图像,则会是下面的图像:
2 hdrwrite函数
2.1 hdrwrite函数用法讲解
hdrwrite函数用法是:
hdrwrite(hdr,filename) 将高动态范围图像hdr写入文件名为filename的文件中
2.2 hdrwrite函数用法示例
我们依然使用office.hdr高动态范围图像,在载入hdr图像后,将其保存到当前文件夹中,并命名为newhdr.hdr。
hdr=hdrread('office.hdr');
hdrwrite(hdr,'newhdr.hdr');
可以看出,新命名的hdr图像就保存到当前文件夹中。
3 makehdr函数
顾名思义,makehdr函数的作用就是创建一个高动态范围图像。
3.1 makehdr函数用法讲解
makehdr函数有以下用法:
HDR=makehdr(files) 从文件files中低动态范围LDR图像集创建单精度高动态范围图像HDR
HDR=makehdr(imds) 从存储为ImageDatastore类型对象imds的一组LDR图像集创建单精度高动态范围图像HDR
HDR=makehdr(_,Name,Value) 此种用法的Name-Value我们会在下面的参数讲解中进行详述
HDR=makehdr(image,Name,Value) 使用存储在单元阵列的LDR图像创建单精度高动态范围图像HDR。通过在Name-Value中使用'ExposureValues'或'RelativeExposure'来指定输入图像的曝光值。
3.2 makehdr函数输入输出参数讲解
输入参数:
- files 是LDR图像集,指定为字符串数组或字符向量的单元数组。可以是灰度图像,也可以是任何位深度的彩色图像。
- imds 是存储为ImageDatastore类型的一组LDR图像集。可以是灰度图像,也可以是任何位深度的彩色图像。
- image 是指定为单元阵列的LDR图像集 ,可以是灰度图像,也可以是任何位深度的彩色图像。
- Name-Value参数
①’BaseFlie’ 曝光基底的文件名
②’ExposureValues’ 输入集中每个图像的曝光值,类型为正数向量,向量中第k个值对应输入集中第k个LDR图像。曝光值的增加意味着曝光值加倍 ,曝光值的减少意味着曝光值减半。
③’RelativeExposure’ 输入集中每个图像的相对曝光值,类型为正数向量,向量中第k个值对应输入集中第k个LDR图像。例如,相对曝光值为0.5的图像的曝光量是曝光值为1的图像的一半。类似地,相对曝光值为3的图像的曝光量是曝光值为1的图像的三倍。
④’MinimumLimit’ 最小曝光值,指定为正整数。对于每个LDR图像,值小于此最小值的像素被认为曝光不足,不会对最终的HDR图像产生影响。默认情况下,此最小值设置为图像数据类型允许的最大强度的2%。
⑤’MaximumLimit’ 最大曝光值,指定为正整数。对于每个LDR图像,值大于此最小值的像素被认为过曝,不会对最终的HDR图像产生影响。默认情况下,此最小值设置为图像数据类型允许的最大强度的98%。
⑥’CameraResponse’ 相机相应函数,对于灰度图像,此参数指定为n×1向量,对于彩色图像,此参数指定为n×3矩阵,相机相应函数将曝光值的对数值映射到输入图像的强度级别。n的值是输入图像位深的2次幂,例如,如果输入图像集的位深度为8,则n为256。
3.3 makehdr函数用法示例
此例中,我们使用一组LDR图像创建HDR图像,这些LDR图像共享相同的f光圈(f-stop),但是曝光时间不同。关于f-stop,网上这篇文章说的很仔细:关于f-stop
首先,我们将这些LDR图像载入到工作区,并创建一个各自相对曝光时间的向量,并用montage函数将其显示出来。关于montage函数,以后的图像显示相关章节会介绍,此处我们只要知道montage函数是将几张图片以矩形方式排列显示。
files={'office_1.jpg','office_2.jpg','office_3.jpg',...
'office_4.jpg','office_5.jpg','office_6.jpg'};
expTimes=[0.0333,0.1000,0.3333,0.6250,1.3000,4.0000];
montage(files);
接下来,我们将这些LDR图片结合成HDR图片并显示:
hdr=makehdr(files,'RelativeExposure',expTimes./expTimes(1));
rgb=tonemap(hdr);
imshow(rgb);
4 tonemap函数
前面小节中,每次显示HDR图像之前,都会用tonemap函数进行处理,在本节就对这个必不可少的tonemap函数进行详细讲解。
4.1 tonemap函数用法讲解
RGB=tonemap(HDR)
RGB=tonemap(HDR,Name,Value)
tonemap函数使用一种叫做色调映射的过程,将HDR图像转换为适合显示的低动态范围RGB图像。色调映射是一种在动态范围有限的显示器上近似显示高动态范围图像的技术。
输入参数讲解:
- HDR m×n×3的高动态范围图像
- Name-Value参数
①’AdjustLightness’ 渲染图像的整体亮度,指定为双元素向量。向量形式为[low high],其中低和高是低动态范围图像的亮度值,在范围(0,1)内。
②’AdjustSaturation’ 渲染图像中颜色的饱和度,指定为正标量。默认为1。当该值大于1时,颜色更加饱和。当值在范围(0,1)内时,颜色的饱和程度较低。
4.2 tonemap函数用法示例
在1.2节中,我们已经对比了不用tonemap函数处理的HDR图像和经过tonemap函数处理之后的rgb图像的区别。接下来,我们使用‘AdjustLightness’和‘AdjustSaturation’参数来对图像的亮度和饱和度进行调整。
hdr=hdrread('office.hdr');
rgb1=tonemap(hdr);
rgb2=tonemap(hdr,'AdjustLightness',[0.3,0.7]);
rgb3=tonemap(hdr,'AdjustSaturation',0.3);
subplot(2,2,1);imshow(hdr);
subplot(2,2,2);imshow(rgb1);
subplot(2,2,3);imshow(rgb2);
subplot(2,2,4);imshow(rgb3);
5 tonemapfarbman函数
5.1 tonemapfarbman函数用法讲解
LDR=tonemapfarbman(HDR)
LDR=tonemapfarbman(HDR,Name,Value)
tonemapfarbman函数将高动态范围(HDR)图像转换为适合显示的低动态范围(LDR)图像,使用称为多尺度色调和细节处理的边缘保持分解的过程。
tonemapfarbman函数的Name-Value参数讲解:
- ‘RangeCompression’ 应用于HDR图像的动态范围压缩量,取值在[0 1]之间,默认为0.3。0代表最小压缩,1代表最大压缩。
- ‘Saturation’ 饱和度,建议取值在[0 5]之间,默认为1.6,随着饱和度值的增加,颜色变得更加丰富和强烈。随着饱和度值的降低,颜色逐渐变为灰色。“Saturation”参数对于灰度HDR图像没有影响。
- ‘Exposure’ 曝光度,建议取值在(0 5]之间,默认为3。随着该值的减小,曝光长度也会减少,因此图像变暗。随着该值的增加,曝光长度也会增加,因此图像会变亮。
5.2 tonemapfarbman函数用法示例
在此示例中,我们将tonemapfarbman函数和tonemap函数进行对比,看看两者的区别。
hdr=hdrread('office.hdr');
ldr1=tonemap(hdr);
ldr2=tonemapfarbman(hdr);
subplot(1,2,1);imshow(ldr1);
subplot(1,2,2);imshow(ldr2);
可以发现,相比于ldr1,ldr2图像更加饱和,亮度更高,但是对比度更差,这是因为,tonemap函数的默认曝光值为1,tonemapfarbman函数的默认曝光值为 3。
我们可以使用参数降低tonemapfarbman函数的曝光值:
ldr3=tonemapfarbman(hdr,'Exposure',1.5);
subplot(1,2,1);imshow(ldr2);
subplot(1,2,2);imshow(ldr3);
可以发现,将曝光值参数’Exposure’从默认值3降为1.5后,图片亮度降低,对比度增强。
6 localtonemap函数
6.1 localtonemap函数用法讲解
RGB=localtonemap(HDR)
RGB=localtonemap(HDR,Name,Value)
localtonemap函数将HDR图像转换为适合显示的低动态范围RGB图像。在使用色调映射的同时保留局部对比度。
localtonemap函数的Name-Value参数讲解:
- ‘RangeCompression’ 含义同tonemapfarbman函数的’RangeCommpression’,默认为1。
- ‘EnhanceContrast’ 局部对比度增强量,取值在[0 1]之间。默认为0。0代表局部对比度不变,1代表最大的局部增强对比度。
6.2 localtonemap函数用法示例
hdr=hdrread('office.hdr');
rgb=localtonemap(hdr,'RangeCompression',0.1);
imshow(rgb);
接着,我们改变输入参数值,再看看效果。
rgb1=localtonemap(hdr,'RangeCompression',0.1,'EnhanceContrast',0.5)
imshow(rgb1);
7 blendexposure函数
7.1 blendexposure函数用法讲解
J=blendexposure(I1,I2,I3,...,In);
J=blendexposure(I1,I2,I3,...,In,Name,Value);
blendexposure函数将具有不同曝光值的灰度图或RGB图像根据图像的对比度、饱和度、曝光度进行合理混合,最终返回曝光良好的图像J。
blendexposure函数参数讲解:
I1,I2,…In:灰度图像或RGB图像。所有的输入图像都必须具有相同的大小和数据类型。
J:输出的混合图像,图像数据大小和数据类型和输入图像一致。
Name-Value参数:
- ‘Contrast’:对比度的权重,默认为1,可以指定为[0 1]内的数。
- ‘Saturation’:饱和度的权重,默认为1,可以指定为[0 1]内的数。
- ‘Wellexposedness’:曝光量的权重,默认为1,可以指定为[0 1]内的数。
- ‘ReduceStrongLight’:可以指定为’true’(default)和’false’,如果“ReduceStrongLight”为真,则blendexposure将尝试抑制图像中强光源的高光。
7.2 blendexposure函数用法实例
在此例中,我们将一系列静止的具有不同曝光值的图像进行融合。
首先读取图像:
I1=imread('car_1.jpg');
I2=imread('car_2.jpg');
I3=imread('car_3.jpg');
I4=imread('car_4.jpg');
montage({I1,I2,I3,I4});
如上图所示,在曝光度不够的图像中,只有像前照灯这样的区域才有详细的信息,而在过曝的图像中,前照灯区域达到饱和,对比度最合适的区域来自于较暗的地方,比如屋顶和地板。
接着,使用blendexposure函数进行图像混合。由于默认的blendexposure函数中’ReduceStrongLight’参数为true,会抑制图像中强光源的高光。作为对比,我们将此参数值设置为false,看看图像混合的效果。
E=blendexposure(I1,I2,I3,I4);
F=blendexposure(I1,I2,I3,I4,'ReduceStrongLight',false);
montage({E,F});
title('Exposure Fusion With (Left) and Without (Right) Strong Light Suppression')
可以看出,融合后的图像中,亮区和暗区都保留了图像细节。前强光抑制融合后的图像E中,前照灯的形状是可以识别的,饱和的像素没有超过前照灯的边界。而在没有强光抑制融合的图像F中,前照灯的形状无法辨认,而且在地面上,由于前照灯的反射也造成某些区域的像素存在饱和。
至此,高动态范围图像HDR相关的函数含义及其使用就已经讲解完毕,我们下个章节见。