Reinhard的HDR色调映射算法参数自动选择版本MatLab程序

Reinhard的HDR色调映射算法参数自动选择版本的具体原理及公式请参见:Erik Reinhard (2002) Parameter Estimation for Photographic Tone Reproduction, Journal of Graphics Tools, 7:1, 45-51, DOI: 10.1080/10867651.2002.10487554。这里我就不再赘述了。下面直接给出代码及其处理效果(算法会根据Zone数,即动态范围,自动选择是用全局映射算法还是局部映射算法):

%% HDR算法复现
% based on the tone mapping technology as described in Erik Reinhard, Michael Stark, 
% Peter Shirley, James Ferwerda, “Photographic Tone Reproduction for Digital Images”
% ACM, 2002
% and Reinhard's “Parameter Estimation for Photographic Tone Reproduction”
% Journal of Graphics Tools, 7:1, 45-51, DOI: 10.1080/10867651.2002.10487554
% author: Zhuangzhuang Zhang
% time: 2020/10/15
close all;clc
filename = 'data/HDR images2/nave.hdr';
try
    hdr = double(hdrread(filename));
catch
    disp('Can not open file!');
    return;
end
if max(size(hdr))>1500
    hdr=imresize(hdr,0.5);
    hdr(hdr<0)=0;
end

gamma=1/1.6;
figure,imshow(hdr.^gamma);
imwrite(hdr.^gamma,'原始HDR图像.png');
%%  预处理,log域均值取指数结果映射到中性灰
Lw = 0.27*hdr(:,:,1) + 0.67*hdr(:,:,2) + 0.06*hdr(:,:,3) + 1e-6; %论文推荐的world luminance计算公式,小偏移量为避免被0除的情况
R = hdr(:,:,1) ./ Lw;
G = hdr(:,:,2) ./ Lw;
B = hdr(:,:,3) ./ Lw;

% maxL=max(L(:));
% settedMaxL=20;
% thL=10;
% mask=L>thL;
% settedMaxL=min(maxL,settedMaxL);
% L(mask)=(settedMaxL-thL)*(L(mask)-thL)/(maxL-thL)+thL;%高曝光部分压缩动态范围

LL=log(Lw+10^-9);
meanLw=exp(mean(LL(:))); %实践中发现将对数均值再反对数变换(取指数)结果映射到key值,通常可以得到更好的效果(主要是大区域之间的对比度更加合理而不会过低)
maxLw=quantile(Lw(:),0.99);
minLw=quantile(Lw(:),0.01);
zone=log2(maxLw)-log2(minLw);
a=0.18*4^((2*log2(meanLw)-log2(minLw)-log2(maxLw))/zone);
L=Lw*a/meanLw;
if zone<11
    Lwhite=1.5*2^(log2(maxLw)-log2(minLw)-5);
    Ld=(L+L.^2/Lwhite^2)./(L+1);
else
    picNum=8;
    ratio=1.3;
    phi=8.0;
    eps=0.05;
    alpha=1/sqrt(8);
    refV=1.0;
    V1=zeros([size(L),picNum+1]); % V2的当前尺度与V1的下一尺度相同
    %-----------------------空域实现-------------------------------%
    tic
    for i=1:picNum+1 % picNum+1个尺度,以ratio为倍数递增
        s=ratio^(i-1);
        sigma=alpha*s;
        kernelRadius = ceil(2*sigma);
        kernelSize = 2*kernelRadius+1;
        gaussKernelHorizontal = fspecial('gaussian', [kernelSize 1], sigma);
        temp= conv2(L, gaussKernelHorizontal, 'same');
        gaussKernelVertical = fspecial('gaussian', [1 kernelSize], sigma);
        V1(:,:,i)= conv2(temp, gaussKernelVertical, 'same');
    end
    V=zeros([size(L),picNum]);
    for i=1:picNum
        s=ratio^(i-1);
        V(:,:,i)=abs(V1(:,:,i+1)-V1(:,:,i))./(a*2^phi/s^2+V1(:,:,i));
    end
    
    Vsm=V1(:,:,picNum); %给Vsm初始化,作为8个尺度都不满足条件下的预设值
    for i=1:size(L,1)
        for j=1:size(L,2)
            for k=1:picNum
                if V(i,j,k)>eps
                    Vsm(i,j)=V1(i,j,k);
                    break;
                end
            end
        end
    end
    
    toc
    figure,imshow(Vsm);
    imwrite(Vsm,'各点参考值图像.png');
    Ld=L./(refV+Vsm);
end
Ld(Ld>1)=1;
figure,imshow(Ld);
%% 色彩还原
rgb=zeros(size(L,1),size(L,2),3);
rgb(:,:,1)=Ld.*R;
rgb(:,:,2)=Ld.*G;
rgb(:,:,3)=Ld.*B;
rgb=rgb.^gamma;
figure,imshow(rgb);

输入图像:

输出(选择了局部色调映射):

输入:

输出(选择了全局色调映射):

可以看出,参数自动选择算法所选的参数和映射策略表现值得肯定。

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值