使用高斯金字塔和拉普拉斯金字塔重构的主要思想就是:高斯金字塔中的内容在高斯模糊并且下采样的过程中会丢失信息,而为了重构出和原图像相差不大的图像,我们则希望能够用某种方式将建立高斯金字塔过程中丢失的信息给保存下来。后来人们想到使用拉普拉斯金字塔来保存这些信息。拉普拉斯金字塔中每层都是高斯金字塔中相邻2层的残差图,也就是相邻2层之间丢失的信息。
算法简述
将原图作为高斯金字塔的第一层,然后使用高斯模糊并下采样得到高斯金字塔的第二层,高斯金字塔的第3层就是对第2层进行高斯模糊并下采样得到的,高斯金字塔的其它层也是通过这样的操作得到的。那么在得到高斯金字塔之后,我们需要求出其相邻2层之间的残差。那么如何求呢?将高斯金子第2层的图像上采样并高斯模糊得到同高斯金字塔第1层图像相同分辨率的图像,然后(第1层-第2层)得到拉普拉斯金字塔第一层图像,然后其第2层图像由(高斯金字塔第2层-高斯金字塔的第3层上采样并高斯模糊得到图像)得到,以此类推。需要注意的是,一般拉普拉斯金字塔的层数比高斯金字塔少一层。当然也有人将高斯金字塔最后一层放入到拉普拉斯金字塔的最后一层,使得2者的层数一样,但是此时拉普拉斯金字塔的最后一层便不再是残差图了,而是原图像的高斯模糊并下采样n次的图像。它同拉普拉斯金字塔的其他层有本质的区别。当拉普拉斯金字塔构建完毕之后,所有的信息都保存好了。接下来就可以重构图像了,使用高斯金字塔最后一层向上采样并平滑,加上拉普拉斯金字塔最后一层的残差(注意这里说的拉普拉斯金字塔比高斯金字塔少一层的情况),再将得到的图像上采样并平滑加上拉普拉斯金字塔倒数第2层,一直这样往复,知道加到拉普拉斯金字塔最低一层结束。那么结果也就是重构好的图像了。
clc;
clear;
close all;
img = imread('images/lena.jpg');
img = im2double(img);
figure;imshow(img);title('原始图像');
nums = 4;
Gau = cell(nums,1);
N =1;
% 原图进高斯金字塔最底层
Gau{N} = img;
% 确定高斯模糊核
a = 0.4;
h = [1/4-a/2 1/4 a 1/4 1/4-a/2];
% ------------------------生成高斯金字塔-------------------------------%
for N = 2:nums
temp = imfilter(Gau{N-1},h,'conv','same','replicate');
temp = imfilter(temp,h','conv','same','replicate');
Gau{N} = temp(1:2:end,1:2:end,:);
end
% 显示高斯金字塔
% for N = 1:nums
% str = sprintf('%s%d%s','高斯金字塔第 ',N,'层');
% figure;imshow(Gau{N});title(str);
% end
% -------------------生成拉普拉斯金字塔-----------------------------------%
str = sprintf('%s%d','现在N = ',N);
disp(str);
Lapla = cell(nums-1,1);
% 拉普拉斯金字塔的最高层等于高斯金字塔的最高层
% 不保留这句话是因为我们可以利用高斯金字塔最高层
% Lapla{N} = Gau{N};
% 得到残差放入拉普拉斯金字塔
for index = nums-1:-1:1
% 上采样
temp = imresize(Gau{index+1},2,'bilinear');
% temp = imresize(Gau{index+1},2,'nearest');
% 高斯模糊
temp = imfilter(temp,h,'conv','same','replicate');
temp = imfilter(temp,h','conv','same','replicate');
Lapla{index} = Gau{index} -temp;
end
% 显示拉普拉斯金字塔
for N = 1:nums-1
str = sprintf('%s%d%s','拉普拉斯金字塔第 ',N,' 层');
figure;imshow(Lapla{N});title(str);
end
% ---------------------利用拉普拉斯金字塔重构-------------------------%
str = sprintf('%s%d','重构开始,现在N = ',N);
disp(str);
% 重构的起点
img_re = Gau{N};
for index = N:-1:2
temp = imresize(Gau{index},2,'bilinear');
% temp = imresize(Gau{index},2,'nearest');
temp = imfilter(temp,h,'conv','same','replicate');
temp = imfilter(temp,h','conv','same','replicate');
img_re = temp + Lapla{index-1};
end
% 计算误差
dif = sum(img_re(:)-img(:));
str =sprintf('%s%f','重构的误差为 ',dif);
disp(str);
figure;imshow(img_re);title('重构的图像');