图像融合之多波段融合(MultibandBlending)拉普拉斯⾦字塔
融合(Laplac。。。
多波段融合⼜叫拉普拉斯⾦字塔融合。
多波段融合的思想是对待融合的图像分别构建拉普拉斯⾦字塔,(拉普拉斯算⼦可以提取出图像的⾼频信息,在拉普拉斯⾦字塔中,越往上层的图像越⾼频)然后对同⼀层图像按照某种规则融合,⼀般是Alpha blending/Feathering;对于不同层图像(不同频率段的图像)进⾏不同规则的融合,⾼频部分blend slowly,低频部分blend quickly;对融合后的图像⾦字塔重建得到最终结果图[1][2]。
Alpha Blending/Feathering:
如何blend:1. 直接对overlap区域average;2.找到center am然后blur am
这⾥最关键点是如何设置window size,window size的设置会对融合效果影响很⼤:
最佳window应该使融合后的图像smooth but not ghosted。在上⾯就是第三副图。
从图像结构特征上考虑,最佳window的约束是这样的:
1.避免产⽣缝需要:window = size of largest prominent feature
2.避免产⽣⿁影需要:window <= 2*size of smallest prominent feature
在频域上上述约束就很好考虑了,融合窗的最⼤频率要<= 2*size of smallest frequency。
如果信号的带宽很⼩,频率都集中在⼀⼩块,很好做决定,但是图像的频率带宽很⼤,分布范围很⼴,这时候就不好确定窗的⼤⼩了。这个问题的解决⽅法就是分频带(band)进⾏Feather。这种⽅法在空间域就能⽅便的实现,就是使⽤带通滤波器(或者等效带通滤波器的⽅法)作⽤于图像得到Bandpass Images。
Pyramid Blending就是其中⼀种优秀的实现⽅法。
The Laplacian Pyramid:
LOG的实现依然是⽤DOG去近似。
拉普拉斯⾦字塔进⾏blending的步骤如下:
1. Build Laplacian pyramids LA and LB from images A and B ;
2. Build a Gaussian pyramid GM from lection mask M;
3. Form a combined pyramid LS from LA and LB using nodes of GM as weights: LS = GM * LA + (1-GM) * LB
4. Collap the LS pyramid to get the final blended image
⼀种Matlab实现[3],⾮常棒,条理清晰:
测试图⽚在此:
注意这⾥处理的是灰度图⽚。
clear all
clo all
clc
%% Read the images, assuming images to be of same size
A=imread('images2\ghost rider.jpg');
B=imread('images2\nicholas cage.jpg');
height=size(A,1);
一千克是多少斤width=size(A,2);
%% Convert images to grayscale
imgA=rgb2gray(A);
imgB=rgb2gray(B);
%% Create mask
partition=floor(width/2);
mask=ones(height,width);
mask(:,1:partition)=0*mask(:,1:partition);霸气微信群名
% figure, imshow(uint8(mask*255));
%% Create gaussian pyramids for both the images and the mask
levels=floor(log2(min([width, height])));
sigma=2;
hsize=3*sigma+1;
sigmaMask=10;
hsizeMask=3*sigmaMask+1;
gaussPyrA=gaussianPyramid(imgA,levels,sigma,hsize)
gaussPyrB=gaussianPyramid(imgB,levels,sigma,hsize)
gaussPyrMask=gaussianPyramid(mask,levels,sigmaMask,hsizeMask)
% for i=1:levels
% figure,imshow(uint8(gaussPyrMask{i,1}*255));
% end
%% Create Laplacian pyramids from both the images
laplacePyrA=laplacianPyramid(gaussPyrA);
laplacePyrB=laplacianPyramid(gaussPyrB);全键盘连发
%% Blend laplacian pyramid
blendedPyr=blendPyramid(laplacePyrA,laplacePyrB,gaussPyrMask);
%% Reconstruct image from blended pyramid
blendedImg=collapPyramid(blendedPyr);
真棒英语
imshow(blendedImg);
对应各步骤的函数:
function pyr=gaussianPyramid(A,levels,sigma,hsize)
pyr=cell(levels,1);
h=fspecial('gaussian',hsize,sigma);
pyr{1,1}=A;
for i=2:levels
temp=imfilter(pyr{i-1,1},h,'symmetric','corr');
pyr{i,1}=temp(1:2:end,1:2:end);
end
function pyr=laplacianPyramid(A)
levels=size(A,1)
pyr=cell(levels,1);
pyr{levels,1}=double(A{levels,1});
for i=levels-1:-1:1
temp=imresize(A{i+1,1},size(A{i,1}));
pyr{i,1}=double(A{i,1})-double(temp);
end
function pyr=blendPyramid(pyrA,pyrB,pyrMask)
levels=size(pyrMask,1);
pyr=cell(levels,1);
for l=1:levels
pyr{l,1}=(1-pyrMask{l,1}).*pyrA{l,1}+(pyrMask{l,1}).*pyrB{l,1};
end
function img=collapPyramid(A)
levels=size(A,1)
for i=levels-1:-1:1
temp=imresize(uint8(A{i+1,1}),size(A{i,1}));
A{i,1}=A{i,1}+double(temp);
end
img=uint8(A{1,1});
下⾯是我仿照上⾯的Matlab 写的基于OpenCV的C++实现:
测试图也是上⾯的链接,同样也是处理灰度图。
漫画头像男
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/photo.hpp>
#include <iostream>
using namespace std;
using namespace cv;天天军棋4399
// show image
void showImage(String windowName, Mat img, int flag = 0)
{
namedWindow(windowName, CV_WINDOW_NORMAL);//0: CV_WINDOW_NORMAL 1: WINDOW_AUTOSIZE imshow(windowName, img);
waitKey(0);
//destroyWindow(windowName);
}
vector<Mat_<float>> gaussianPyramid(Mat img, int levels)
{
{
vector<Mat_<float>> _gaussianPyramid;
_gaussianPyramid.push_back(img);
Mat currentImage = img;
//cout << currentImage.size() << endl;
for (int i = 1; i < levels; i++)
{
Mat downsampleImage;土豆排骨的做法
pyrDown(currentImage, downsampleImage); // Blurs an image and downsamples it.
_gaussianPyramid.push_back(downsampleImage);
//showImage("currentImage", currentImage);
//cout << downsampleImage.size() << endl;
currentImage = downsampleImage;
}
return _gaussianPyramid;
}
vector<Mat_<float>> laplacianPyramid(vector<Mat_<float>> gaussPyrImg)
{
int levels = gaussPyrImg.size();
vector<Mat_<float>> _laplacianPyramid;
_laplacianPyramid.push_back(gaussPyrImg[levels - 1]);// order rever !!
//cout << gaussPyrImg[levels - 1].size() << endl;
for (int i = levels - 2 ; i >= 0; i--)
{
Mat upsampleImage;
pyrUp(gaussPyrImg[i + 1], upsampleImage, gaussPyrImg[i].size());
Mat currentImage = gaussPyrImg[i] - upsampleImage;
//showImage("currentImage", currentImage);
/
/cout << currentImage.size() << endl;
_laplacianPyramid.push_back(currentImage);
}
return _laplacianPyramid;
忆想}
vector<Mat_<float>> blendPyramid(vector<Mat_<float>> pyrA, vector<Mat_<float>> pyrB, vector<Mat_<float>> pyrMask) {
int levels = pyrA.size();
vector<Mat_<float>> blendedPyramid;
for (int i = 0; i < levels; i++)
{
Mat blendedImage = pyrA[i].mul(1.0 - pyrMask[levels -1 - i]) + pyrB[i].mul(pyrMask[levels - 1 - i]);
//showImage("blendedImage", blendedImage);
blendedPyramid.push_back(blendedImage);
}
return blendedPyramid;
}
Mat collapPyramid(vector<Mat_<float>> blendedPyramid)
{
int levels = blendedPyramid.size();
Mat currentImage = blendedPyramid[0];
for (int i = 1; i < levels; i++)
{
pyrUp(currentImage, currentImage, blendedPyramid[i].size());
currentImage += blendedPyramid[i];
//showImage("currentImage", currentImage);
}
Mat blendedImage;
convertScaleAbs(currentImage, blendedImage, 255.0);
return blendedImage;
}
int main()