先选定两幅曝光差异很大的图:
和
然后送到OPENCV里面用前几篇写过的 进行特征点检测和匹配 再把匹配对输出存为txt文件 然后送给MATLAB读取 在MATLAB里面用之前我写过的那个计算H矩阵 并进行H矩阵变换 得到:
得到这个结果 然后试试之前写过的那个渐入渐出融合(在MATLAB里) 结果:
可以看到 渐入渐出等线性融合解决不了鬼影问题以及曝光差异问题
然后试试最佳缝合线拼接 (MATLAB里之前写过的程序)结果:
可以清晰的看到选出来的最佳线 然后继续在MATLAB里进行多分辨率拼接第一步:即将原图和模板都扩充到这样大小 结果:
之前看的论文里要么不说具体怎么填充 是用replicate填充还是用别的填充或者直接用0填充 要么说了原图用0填充却没说右边这幅应该0填到左边 而且还说模板是这样填充 左0右255 其实是错的 因为这样的结果出来是这样:
论文啊我一直都抱着怀疑的态度看每篇论文 但没想到发到核心期刊的论文也有笔误 所以其实是左边255右边0:
%将原图及模板都扩大到这么大 紧接着之前的最佳缝合线拼接算法程序bestlinefusion.m
%[m,n,k]=size(D);
%E=uint8(zeros(m,n,k));
%[ma,na,ka]=size(A);
%for i=1:ma
% for j=1:na
% E(i,j,1)=A(i,j,1);
% E(i,j,2)=A(i,j,2);
% E(i,j,3)=A(i,j,3);
% end
%end
%F=uint8(zeros(m,n,k));
%[mb,nb,kb]=size(B);
%L=n-nb+1;
%for i=1:mb
% for j=L:n
% F(i,j,1)=B(i,j-(n-nb),1);
% F(i,j,2)=B(i,j-(n-nb),2);
% F(i,j,3)=B(i,j-(n-nb),3);
% end
%end
%G=uint8(zeros(m,n,k));
%L=W+1+rdata1;
%for i=1:m
% for j=L+mypath(i):n
% G(i,j,1)=255;
% G(i,j,2)=255;
% G(i,j,3)=255;
% end
%end
%上面是模板 模板应该左白右黑 原图一个在左右边填0 另一幅在右左边填0
然后再把填充好的这三幅图放进OPENCV里 得到laplacian金字塔 然后每阶上进行融合 再相加重建融合结果的原图:
#include "opencv2/opencv.hpp"
using namespace cv;
class LaplacianBlending {
private:
Mat_<Vec3f> left;
Mat_<Vec3f> right;
Mat_<float> blendMask;
vector<Mat_<Vec3f> > leftLapPyr,rightLapPyr,resultLapPyr;//Laplacian Pyramids
Mat leftHighestLevel, rightHighestLevel, resultHighestLevel;
vector<Mat_<Vec3f> > maskGaussianPyramid; //masks are 3-channels for easier multiplication with RGB
int levels;
void buildPyramids() {
buildLaplacianPyramid(left,leftLapPyr,leftHighestLevel);
buildLaplacianPyramid(right,rightLapPyr,rightHighestLevel);
buildGaussianPyramid();
}
void buildGaussianPyramid() {//金字塔内容为每一层的掩模
assert(leftLapPyr.size()>0);
maskGaussianPyramid.clear();
Mat currentImg;
cvtColor(blendMask, currentImg, CV_GRAY2BGR);//store color img of blend mask into maskGaussianPyramid
maskGaussianPyramid.push_back(currentImg); //0-level
currentImg = blendMask;
for (int l=1; l<levels+1; l++) {
Mat _down;
if (leftLapPyr.size()>l)
pyrDown(currentImg, _down, leftLapPyr[l].size());
else
pyrDown(currentImg, _down, leftHighestLevel.size()); //lowest level
Mat down;
cvtColor(_down, down, CV_GRAY2BGR);
maskGaussianPyramid.push_back(down);//add color blend mask into mask Pyramid
currentImg = _down;
}
}
void buildLaplacianPyramid(const Mat& img, vector<Mat_<Vec3f> >& lapPyr, Mat& HighestLevel) {
lapPyr.clear();
Mat currentImg = img;
for (int l=0; l<levels; l++) {
Mat down,up;
pyrDown(currentImg, down);
pyrUp(down, up,currentImg.size());
Mat lap = currentImg - up;
lapPyr.push_back(lap);
currentImg = down;
}
currentImg.copyTo(HighestLevel);
}
void blendLapPyrs()
{
resultHighestLevel = leftHighestLevel.mul(maskGaussianPyramid.back()) +rightHighestLevel.mul(Scalar(1.0,1.0,1.0) - maskGaussianPyramid.back());
//以上得到的是最高阶的上一阶的融合图
for (int l=0; l<levels; l++)
{
Mat A = leftLapPyr[l].mul(maskGaussianPyramid[l]);
Mat antiMask = Scalar(1.0,1.0,1.0) - maskGaussianPyramid[l];
Mat B = rightLapPyr[l].mul(antiMask);
Mat_<Vec3f> blendedLevel = A + B;
resultLapPyr.push_back(blendedLevel);
}
}
Mat_<Vec3f> reconstructImgFromLapPyramid() {
//将左右laplacian图像拼成的resultLapPyr金字塔中每一层
//从上到下插值放大并相加,即得blend图像结果
Mat currentImg = resultHighestLevel;
for (int l=levels-1; l>=0; l--) {
Mat up;
pyrUp(currentImg, up, resultLapPyr[l].size());
currentImg = up + resultLapPyr[l];
}
return currentImg;
}
public:
LaplacianBlending(const Mat_<Vec3f>& _left, const Mat_<Vec3f>& _right, const Mat_<float>& _blendMask, int _levels)://construct function, used in LaplacianBlending lb(l,r,m,4);
left(_left),right(_right),blendMask(_blendMask),levels(_levels)
{
assert(_left.size() == _right.size());
assert(_left.size() == _blendMask.size());
buildPyramids(); //construct Laplacian Pyramid and Gaussian Pyramid
blendLapPyrs(); //blend left & right Pyramids into one Pyramid
};
Mat_<Vec3f> blend() {
return reconstructImgFromLapPyramid();//reconstruct Image from Laplacian Pyramid
}
};
Mat_<Vec3f> LaplacianBlend(const Mat_<Vec3f>& l, const Mat_<Vec3f>& r, const Mat_<float>& m) {
LaplacianBlending lb(l,r,m,5);
return lb.blend();
}
int main()
{
Mat l8u = imread("left.jpg");
Mat r8u = imread("right.jpg");
imshow("left",l8u);
imshow("right",r8u);
Mat_<Vec3f> l;
l8u.convertTo(l,CV_32F,1.0/255.0);//Vec3f表示有三个通道,即 l[row][column][depth]
Mat_<Vec3f> r;
r8u.convertTo(r,CV_32F,1.0/255.0);
//Mat_<float> m(l.rows,l.cols,0.0); //将m全部赋值为0
//m(Range::all(),Range(0,m.cols/2)) = 1.0; //取m全部行&[0,m.cols/2]列,赋值为1.0
//上面这个模板m要改 改成最佳缝合线得到的结果C的样子
Mat_<float> m(l.rows,l.cols,0.0);
Mat C=imread("CC.jpg");
for(int i=0;i<l.rows;i++)
{
for(int j=0;j<l.cols;j++)
{
if(C.at<Vec3b>(i,j)[0]!=0&&C.at<Vec3b>(i,j)[1]!=0&&C.at<Vec3b>(i,j)[2]!=0) // 因为我要的只是位置
m(i,j)=1.0;
}
}
Mat_<Vec3f> blend = LaplacianBlend(l, r, m);
imshow("blended",blend);
waitKey(0);
return 0;
}
结果:可以看到没有重影(因为利用了最佳缝合线避开了重影)以及曝光差异大大减弱(多分辨率融合)!但是竖直方向有误差 因为我开始只用了rdata1 没有将计算得到的竖直方向的rdata2用进去。
对比下OPENCV里stitch里自带的效果:
忽略竖直方向我没有用的误差 其它好像差不多 但看着还是比我的多分辨率要舒服 不愧是封装进OpenCV里的可以直接调用的cpp!
下面是一步步探索的过程 搞了好几天终于得到上面正确的程序了 下面探索是有问题的 有的是这里错有的那里错 有的错的原因我现在还没弄太清:
根据《图像拼接的改进算法》在完成最佳缝合线算法之后,要进行多分辨率拼接,这些完成后不仅能消除 曝光差异还能消除鬼影重影问题,所以我重新选了两个曝光差异很大的图片:
曝光差异很大 经过最佳缝合线以后:
可以清楚地看到这条选出的最佳缝合线
然后开始进行多分辨率拼接 理论就继续根据这篇论文 因为步骤写得很清楚:
1 ,第一步 将原图扩大到拼接图大小 并另外填充一幅图缝合线左边为白右边为黑色 结果:
分别叫AA、BB、CC
第二步 对两图求laplace金字塔 对黑白图求gaussian金字塔:
求金字塔,这个之前暑假学OpenCV的时候浅墨大神博客里有讲过,所以就直接用之前学OPENCV的时候的,不过有个疑惑,laplace金字塔是上采样,即对AA、BB上采样得到laplace金字塔;对CC进行下采样得到gaussian金字塔,可是这个论文里这个相加的公式感觉有点模糊啊比如(i,j)这个点AA、BB金字塔有对应点,但CC是下采样 图片越来越小 那它可能没有这个点了 那怎么作为权重与AA、BB的像论文里那样相加呢??
这步是在OpenCV里运行的:
int main()
{
Mat src1=imread("AA.jpg");
Mat src2=imread("BB.jpg");
Mat src3=imread("CC.jpg");
if(!src1.data||!src2.data||!src3.data)
{
cout<<"damn!wrong in reading!"<<endl;
return -1;
}
Mat dst11,dst12,dst13,dst14,dst15,dst21,dst22,dst23,dst24,dst25,dst31,dst32,dst33,dst34,dst35;
pyrUp(src1, dst11, Size(src1.cols*2,src1.rows*2 ) );//上采样 laplace
imshow("src1的laplace1", dst11);
pyrUp(dst11, dst12, Size(dst11.cols*2,dst11.rows*2) );
imshow("src1的laplace2",dst12);
pyrUp(dst12, dst13, Size(dst12.cols*2,dst12.rows*2) );
imshow("src1的laplace3",dst13);
pyrUp(dst13, dst14, Size(dst13.cols*2,dst13.rows*2) );
imshow("src1的laplace4",dst14);
pyrUp(dst14, dst15, Size(dst14.cols*2,dst14.rows*2) );
imshow("src1的laplace5",dst15);
imwrite("src1laplace1.jpg",dst11);
imwrite("src1laplace2.jpg",dst12);
imwrite("src1laplace3.jpg",dst13);
imwrite("src1laplace4.jpg",dst14);
imwrite("src1laplace5.jpg",dst15);
pyrUp(src2, dst21, Size(src2.cols*2,src2.rows*2 ) );
imshow("src2的laplace1",dst21);
pyrUp(dst21, dst22, Size(dst21.cols*2,dst21.rows*2) );
imshow("src2的laplace2",dst22);
pyrUp(dst22, dst23, Size(dst22.cols*2,dst22.rows*2) );
imshow("src2的laplace3",dst23);
pyrUp(dst23, dst24, Size(dst23.cols*2,dst23.rows*2) );
imshow("src2的laplace4",dst24);
pyrUp(dst24, dst25, Size(dst24.cols*2,dst24.rows*2) );
imshow("src2的laplace5",dst25);
imwrite("src2laplace1.jpg",dst21);
imwrite("src2laplace2.jpg",dst22);
imwrite("src2laplace3.jpg",dst23);
imwrite("src2laplace4.jpg",dst24);
imwrite("src2laplace5.jpg",dst25);
pyrDown(src3, dst31, Size(src3.cols/2,src3.rows/2) ); //下采样
imshow("src3的Gaussian1",dst31);
pyrDown(dst31, dst32, Size(dst31.cols/2,dst31.rows/2) );
imshow("src3的Gaussian2",dst32);
pyrDown(dst32, dst33, Size(dst32.cols/2,dst32.rows/2) );
imshow("src3的Gaussian3",dst33);
pyrDown(dst33, dst34, Size(dst33.cols/2,dst33.rows/2) );
imshow("src3的Gaussian4",dst34);
pyrDown(dst34, dst35, Size(dst34.cols/2,dst34.rows/2) );
imshow("src3的Gaussian5",dst35);
imwrite("src3gaussian1.jpg",dst31);
imwrite("src3gaussian2.jpg",dst32);
imwrite("src3gaussian3.jpg",dst33);
imwrite("src3gaussian4.jpg",dst34);
imwrite("src3gaussian5.jpg",dst35);
return 0;
}
咦下面传上来是一样大小了 应该是CSDN里规定了 其实是不一样大小的 但是这样传上来也看不出来变化,,,,反正是不一样大小的
本来有5阶的 但最后一幅图传不上来 说超过了限制 所以只传4阶的 拉普拉斯图像 下面是第二幅图的4阶拉普拉斯金字塔:
下面是黑白图CC的高斯金字塔图 因为是下采样 所以5阶都可以上传:
在这一步 我发现原来每次都只可以x2 或者/2 之前我以为可以x3或者x4 太傻了 原来每次都只能x2或者/2
第三步 :按照论文公式得到融合图的laplacian金字塔图像 (在MATLAB上)
%计算第0阶融合图的laplace金字塔DD0
AA=imread('F:\fisheye\AA.jpg');
BB=imread('F:\fisheye\BB.jpg');
CC=imread('F:\fisheye\CC.jpg');
[m0,n0,k0]=size(AA);
DD0=zeros(m0,n0);
for i=1:m0
for j=1:n0
DD0(i,j,1)=CC(i,j,1)*AA(i,j,1)+(1-CC(i,j,1))*BB(i,j,1);
DD0(i,j,2)=CC(i,j,2)*AA(i,j,2)+(1-CC(i,j,2))*BB(i,j,2);
DD0(i,j,3)=CC(i,j,3)*AA(i,j,3)+(1-CC(i,j,3))*BB(i,j,3);
end
end
DD0=uint8(DD0);
%计算第1阶融合图的laplace金字塔DD1
AA1=imread('F:\fisheye\src1laplace1.jpg');
BB1=imread('F:\fisheye\src2laplace1.jpg');
CC1=imread('F:\fisheye\src3gaussian1.jpg');
[m1,n1,k1]=size(AA1);
CC1=imresize(CC1,[m1,n1]);
DD1=zeros(m1,n1);
for i=1:m1
for j=1:n1
DD1(i,j,1)=CC1(i,j,1)*AA1(i,j,1)+(1-CC1(i,j,1))*BB1(i,j,1);
DD1(i,j,2)=CC1(i,j,2)*AA1(i,j,2)+(1-CC1(i,j,2))*BB1(i,j,2);
DD1(i,j,3)=CC1(i,j,3)*AA1(i,j,3)+(1-CC1(i,j,3))*BB1(i,j,3);
end
end
DD1=uint8(DD1);
%计算第2阶
AA2=imread('F:\fisheye\src1laplace2.jpg');
BB2=imread('F:\fisheye\src2laplace2.jpg');
CC2=imread('F:\fisheye\src3gaussian2.jpg');
[m2,n2,k2]=size(AA2);
CC2=imresize(CC2,[m2,n2]);
DD2=zeros(m2,n2);
for i=1:m2
for j=1:n2
DD2(i,j,1)=CC2(i,j,1)*AA2(i,j,1)+(1-CC2(i,j,1))*BB2(i,j,1);
DD2(i,j,2)=CC2(i,j,2)*AA2(i,j,2)+(1-CC2(i,j,2))*BB2(i,j,2);
DD2(i,j,3)=CC2(i,j,3)*AA2(i,j,3)+(1-CC2(i,j,3))*BB2(i,j,3);
end
end
DD2=uint8(DD2);
%计算第3阶
AA3=imread('F:\fisheye\src1laplace3.jpg');
BB3=imread('F:\fisheye\src2laplace3.jpg');
CC3=imread('F:\fisheye\src3gaussian3.jpg');
[m3,n3,k3]=size(AA3);
CC3=imresize(CC3,[m3,n3]);
DD3=zeros(m3,n3);
for i=1:m3
for j=1:n3
DD3(i,j,1)=CC3(i,j,1)*AA3(i,j,1)+(1-CC3(i,j,1))*BB3(i,j,1);
DD3(i,j,2)=CC3(i,j,2)*AA3(i,j,2)+(1-CC3(i,j,2))*BB3(i,j,2);
DD3(i,j,3)=CC3(i,j,3)*AA3(i,j,3)+(1-CC3(i,j,3))*BB3(i,j,3);
end
end
DD3=uint8(DD3);
%计算第4阶
AA4=imread('F:\fisheye\src1laplace4.jpg');
BB4=imread('F:\fisheye\src2laplace4.jpg');
CC4=imread('F:\fisheye\src3gaussian4.jpg');
[m4,n4,k4]=size(AA4);
CC4=imresize(CC4,[m4,n4]);
DD4=zeros(m4,n4);
for i=1:m4
for j=1:n4
DD4(i,j,1)=CC4(i,j,1)*AA4(i,j,1)+(1-CC4(i,j,1))*BB4(i,j,1);
DD4(i,j,2)=CC4(i,j,2)*AA4(i,j,2)+(1-CC4(i,j,2))*BB4(i,j,2);
DD4(i,j,3)=CC4(i,j,3)*AA4(i,j,3)+(1-CC4(i,j,3))*BB4(i,j,3);
end
end
DD4=uint8(DD4);
%相加 所有阶 得到融合后图DD
DD3=imresize(DD3,[m4 n4]);
DD2=imresize(DD2,[m4 n4]);
DD1=imresize(DD1,[m4 n4]);
DD0=imresize(DD0,[m4 n4]);
DD=DD4+DD3;
DD=DD+DD2;
DD=DD+DD1;
DD=DD+DD0;
我是这样来算的 结果第0阶融合后的图DD0为:
这是第0阶融合后的图 怎么感觉怪怪的
so strange!后面做了第四步:相加得融合图 可是也不对 应该是有问题的 反正根据《图像拼接的改进算法》编出来是这样 是有问题的 不知道是论文说得不清楚还是我自己不行 我再找找别的论文 。
我找到这个作者写的一篇博士毕业论文 《图像拼接技术研究》重新看了下他在这里面写的多分辨率拼接部分:发现不只是像他在期刊上发的那篇那样简单, 这里面就写得详细些:这些那个期刊文章里就没有讲过 所以我也完全没往这方面编 我再重新编下试试。
重新看了两篇论文《基于多分辨率融合的无人机图像拼接匀色研究》、《图像拼接技术研究》知道了不是像期刊里那样简单四步就OK了 那个期刊里只写出了简单步骤 但具体的实现细节 还是看这两篇:
1,第一步和上面的第一步一样 扩充到拼接图的大小 即得到AA、BB、CC 和上面的第一步一样
2,第二步 和上面的不一样 将AA、BB、CC作为第0阶的 总共我用了5阶 即0-----4阶 应该是下采样得到高斯金字塔 对AA、BB、CC都这样得到它们的五阶高斯金字塔图像
int main()
{
Mat src1=imread("AA.jpg");
Mat src2=imread("BB.jpg");
Mat src3=imread("CC.jpg");
if(!src1.data||!src2.data||!src3.data)
{
cout<<"damn!wrong in reading!"<<endl;
return -1;
}
Mat dst11,dst12,dst13,dst14,dst15,dst21,dst22,dst23,dst24,dst25,dst31,dst32,dst33,dst34,dst35;
pyrDown(src1, dst11, Size(src1.cols/2,src1.rows/2 ) );
imshow("src1的laplace1", dst11);
pyrDown(dst11, dst12, Size(dst11.cols/2,dst11.rows/2) );
imshow("src1的laplace2",dst12);
pyrDown(dst12, dst13, Size(dst12.cols/2,dst12.rows/2) );
imshow("src1的laplace3",dst13);
pyrDown(dst13, dst14, Size(dst13.cols/2,dst13.rows/2) );
imshow("src1的laplace4",dst14);
imwrite("src1gaussian1.jpg",dst11);
imwrite("src1gaussian2.jpg",dst12);
imwrite("src1gaussian3.jpg",dst13);
imwrite("src1gaussian4.jpg",dst14);
pyrDown(src2, dst21, Size(src2.cols/2,src2.rows/2 ) );
imshow("src2的laplace1",dst21);
pyrDown(dst21, dst22, Size(dst21.cols/2,dst21.rows/2) );
imshow("src2的laplace2",dst22);
pyrDown(dst22, dst23, Size(dst22.cols/2,dst22.rows/2) );
imshow("src2的laplace3",dst23);
pyrDown(dst23, dst24, Size(dst23.cols/2,dst23.rows/2) );
imshow("src2的laplace4",dst24);
imwrite("src2gaussian1.jpg",dst21);
imwrite("src2gaussian2.jpg",dst22);
imwrite("src2gaussian3.jpg",dst23);
imwrite("src2gaussian4.jpg",dst24);
pyrDown(src3, dst31, Size(src3.cols/2,src3.rows/2) );
imshow("src3的Gaussian1",dst31);
pyrDown(dst31, dst32, Size(dst31.cols/2,dst31.rows/2) );
imshow("src3的Gaussian2",dst32);
pyrDown(dst32, dst33, Size(dst32.cols/2,dst32.rows/2) );
imshow("src3的Gaussian3",dst33);
pyrDown(dst33, dst34, Size(dst33.cols/2,dst33.rows/2) );
imshow("src3的Gaussian4",dst34);
imwrite("src3gaussian1.jpg",dst31);
imwrite("src3gaussian2.jpg",dst32);
imwrite("src3gaussian3.jpg",dst33);
imwrite("src3gaussian4.jpg",dst34);
return 0;
}
上面我是在OpenCV里得到的 ,然后接下来去MATLAB里做,对AA、BB的五阶金字塔图像进行高斯低通滤波:
接下来是对原图BB进行低通滤波 得到一样的五阶高斯金字塔的图,接下来就对第1阶的插值扩大到第0阶一样大小 再相减 这样得到第0阶的拉普拉斯金字塔;同理对第2阶的插值扩大到第1阶一样大小 再相减 这样就得到第1阶拉普拉斯图像,,,依次类推 按照《多分辨率融合在无人机中的匀色研究》中的公式 但插值那里我没有按照它说的 我直接用的imresize的默认的最近邻插值 看行不行
A0=imread('F:\fisheye\AA.jpg');
w=fspecial('gaussian',[5 5],1.6);
AA0=imfilter(A0,w,'replicate');
A1=imread('F:\fisheye\src1gaussian1.jpg');
AA1=imfilter(A1,w,'replicate');
A2=imread('F:\fisheye\src1gaussian2.jpg');
AA2=imfilter(A2,w,'replicate');
A3=imread('F:\fisheye\src1gaussian3.jpg');
AA3=imfilter(A3,w,'replicate');
A4=imread('F:\fisheye\src1gaussian4.jpg');
AA4=imfilter(A4,w,'replicate');
a4=AA4;
[m3,n3,k3]=size(AA3);
AA4=imresize(AA4,[m3 n3]);
a3=AA3-AA4;
[m2,n2,k2]=size(AA2);
AA3=imresize(AA3,[m2 n2]);
a2=AA2-AA3;
[m1,n1,k1]=size(AA1);
AA2=imresize(AA2,[m1 n1]);
a1=AA1-AA2;
[m0,n0,k0]=size(AA0);
AA1=imresize(AA1,[m0 n0]);
>> a0=AA0-AA1;
>> imwrite(a0,'a0.jpg');
>> imwrite(a1,'a1.jpg');
>> imwrite(a2,'a2.jpg');
>> imwrite(a3,'a3.jpg');
>> imwrite(a4,'a4.jpg');
对BB也这样 可以得到五阶拉普拉斯金字塔:
B0=imread('F:\fisheye\BB.jpg');
>> BB0=imfilter(B0,w,'replicate');
>> B1=imread('F:\fisheye\src2gaussian1.jpg');
>> BB1=imfilter(B1,w,'replicate');
>> B2=imread('F:\fisheye\src2gaussian2.jpg');
>> BB2=imfilter(B2,w,'replicate');
>> B3=imread('F:\fisheye\src2gaussian3.jpg');
>> BB3=imfilter(B3,w,'replicate');
>> B4=imread('F:\fisheye\src2gaussian4.jpg');
>> BB4=imfilter(B4,w,'replicate');
>> b4=BB4;
>> [m3,n3,k3]=size(BB3);
>> BB4=imresize(BB4,[m3 n3]);
>> b3=BB3-BB4;
>> [m2,n2,k2]=size(BB2);
>> BB3=imresize(BB3,[m2 n2]);
>> b2=BB2-BB3;
>> [m1,n1,k1]=size(BB1);
>> BB2=imresize(BB2,[m1 n1]);
>> b1=BB1-BB2;
>> [m0,n0,k0]=size(BB0);
>> BB1=imresize(BB1,[m0 n0]);
>> b0=BB0-BB1;
>> imwrite(b0,'b0.jpg');
>> imwrite(b1,'b1.jpg');
>> imwrite(b2,'b2.jpg');
>> imwrite(b3,'b3.jpg');
>> imwrite(b4,'b4.jpg');
这得到的是两幅图的laplacian金字塔 共五阶 第五阶没得减按照这个论文里公式 直接等于那阶的高斯图 所以就成了上面那样
3,进行每一阶的laplacian融合 得到融合图D的laplacian金字塔图像d0、d1、d2、d3、d4 还是按照论文里公式
a0=imread('F:\fisheye\a0.jpg');
a1=imread('F:\fisheye\a1.jpg');
a2=imread('F:\fisheye\a2.jpg');
a3=imread('F:\fisheye\a3.jpg');
a4=imread('F:\fisheye\a4.jpg');
b0=imread('F:\fisheye\b0.jpg');
b1=imread('F:\fisheye\b1.jpg');
b2=imread('F:\fisheye\b2.jpg');
b3=imread('F:\fisheye\b3.jpg');
b4=imread('F:\fisheye\b4.jpg');
c0=imread('F:\fisheye\CC.jpg');
c1=imread('F:\fisheye\src3gaussian1.jpg');
c2=imread('F:\fisheye\src3gaussian2.jpg');
c3=imread('F:\fisheye\src3gaussian3.jpg');
c4=imread('F:\fisheye\src3gaussian4.jpg');
[m0,n0,k0]=size(a0);
d0=zeros(m0,n0);
for i=1:m0
for j=1:n0
d0(i,j,1)=c0(i,j,1)*a0(i,j,1)+(1-c0(i,j,1))*b0(i,j,1);
d0(i,j,2)=c0(i,j,2)*a0(i,j,2)+(1-c0(i,j,2))*b0(i,j,2);
d0(i,j,3)=c0(i,j,3)*a0(i,j,3)+(1-c0(i,j,3))*b0(i,j,3);
end
end
d0=uint8(d0);
[m1,n1,k1]=size(a1);
d1=zeros(m1,n1);
for i=1:m1
for j=1:n1
d1(i,j,1)=c1(i,j,1)*a1(i,j,1)+(1-c1(i,j,1))*b1(i,j,1);
d1(i,j,2)=c1(i,j,2)*a1(i,j,2)+(1-c1(i,j,2))*b1(i,j,2);
d1(i,j,3)=c1(i,j,3)*a1(i,j,3)+(1-c1(i,j,3))*b1(i,j,3);
end
end
d1=uint8(d1);
[m2,n2,k2]=size(a2);
d2=zeros(m2,n2);
for i=1:m2
for j=1:n2
d2(i,j,1)=c2(i,j,1)*a2(i,j,1)+(1-c2(i,j,1))*b2(i,j,1);
d2(i,j,2)=c2(i,j,2)*a2(i,j,2)+(1-c2(i,j,2))*b2(i,j,2);
d2(i,j,3)=c2(i,j,3)*a2(i,j,3)+(1-c2(i,j,3))*b2(i,j,3);
end
end
>> d2=uint8(d2);
>> [m3,n3,k3]=size(a3);
>> d3=zeros(m3,n3);
>> for i=1:m3
for j=1:n3
d3(i,j,1)=c3(i,j,1)*a3(i,j,1)+(1-c3(i,j,1))*b3(i,j,1);
d3(i,j,2)=c3(i,j,2)*a3(i,j,2)+(1-c3(i,j,2))*b3(i,j,2);
d3(i,j,3)=c3(i,j,3)*a3(i,j,3)+(1-c3(i,j,3))*b3(i,j,3);
end
end
>> d3=uint8(d3);
>> [m4,n4,k4]=size(a4);
>> d4=zeros(m4,n4);
>> for i=1:m4
for j=1:n4
d4(i,j,1)=c4(i,j,1)*a4(i,j,1)+(1-c4(i,j,1))*b4(i,j,1);
d4(i,j,2)=c4(i,j,2)*a4(i,j,2)+(1-c4(i,j,2))*b4(i,j,2);
d4(i,j,3)=c4(i,j,3)*a4(i,j,3)+(1-c4(i,j,3))*b4(i,j,3);
end
end
>> d4=uint8(d4);
4,第四步 即最后一步 对于d4--d0这五阶 从高阶插值加上下一阶 直到加到d0为止 这样就得到了融合后图D
[m3,n3,k3]=size(d3);
>> d4=imresize(d4,[m3,n3]);
>> D=d4+d3;
>> [m2,n2,k2]=size(d2);
>> D=imresize(D,[m2,n2]);
>> D=D+d2;
>> [m1,n1,k1]=size(d1);
>> D=imresize(D,[m1,n1]);
>> D=D+d1;
>> [m0,n0,k0]=size(d0);
>> D=imresize(D,[m0,n0]);
>> D=D+d0;
按道理来说这个D就是最终得到的融合图 可是为什么成了这样?
我上面与《基于多分辨率融合的无人机图像拼接匀色研究》就是插值那里和高斯核函数那里不一样 可是按道理来说不应该成这样啊 至少也要像融合后的图啊 不对!
后来大叔又给我看了这个http://www.360doc.com/content/15/1103/17/27378135_510480683.shtml# 又思考了思考 这个文档里又补充了上面论文里的细节 于是还是重新按照这个再编一次 看看:
好了 重新编 根据《基于多分辨率融合的无人机图像拼接匀色研究》我还是不用MATLAB里面自带的fspecial、imfilter函数,因为核窗口和论文里规定的不一样,所以自己生成吧 还有我试试先转化成灰度图
1,得到高斯金字塔
%《基于多分辨率融合的无人机图像拼接匀色研究》多分辨率拼接 先转化成灰度图像
A0=imread('F:\fisheye\AA.jpg');
%原图是第0阶
A0=rgb2gray(A0);
w=[1/256,4/256,6/256,4/256,1/256;4/256,16/256,24/256,16/256,4/256;6/256,24/256,36/256,24/256,6/256;4/256,16/256,24/256,16/256,4/256;1/256,4/256,6/256,4/256,1/256];
%降采样 高斯低通滤波得到第一阶
[m0,n0]=size(A0);
m1=fix(m0/2);
n1=fix(n0/2);
A1=zeros(m1,n1);
for i=1:m1
for j=1:n1
if (2*j-2<1&&2*i-2<1)
A1(i,j)=w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(2,5)*A0(2*i-1,2*j+2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(3,5)*A0(2*i,2*j+2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1)+w(4,5)*A0(2*i+1,2*j+2)+w(5,2)*A0(2*i+2,2*j-1)+w(5,3)*A0(2*i+2,2*j)+w(5,4)*A0(2*i+2,2*j+1)+w(5,5)*A0(2*i+2,2*j+2);
else
if(2*i-2<1&&2*j+2>n0)
A1(i,j)=+w(2,1)*A0(2*i-1,2*j-2)+w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(3,1)*A0(2*i,2*j-2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(4,1)*A0(2*i+1,2*j-2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1)+w(5,1)*A0(2*i+2,2*j-2)+w(5,2)*A0(2*i+2,2*j-1)+w(5,3)*A0(2*i+2,2*j)+w(5,4)*A0(2*i+2,2*j+1);
else
if(2*i+2>m0&&2*j-2<1)
A1(i,j)=w(1,2)*A0(2*i-2,2*j-1)+w(1,3)*A0(2*i-2,2*j)+w(1,4)*A0(2*i-2,2*j+1)+w(1,5)*A0(2*i-2,2*j+2)+w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(2,5)*A0(2*i-1,2*j+2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(3,5)*A0(2*i,2*j+2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1)+w(4,5)*A0(2*i+1,2*j+2);
else
if(2*i+2>m0&&2*j+2>n0)
A1(i,j)=w(1,1)*A0(2*i-2,2*j-2)+w(1,2)*A0(2*i-2,2*j-1)+w(1,3)*A0(2*i-2,2*j)+w(1,4)*A0(2*i-2,2*j+1)+w(2,1)*A0(2*i-1,2*j-2)+w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(3,1)*A0(2*i,2*j-2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(4,1)*A0(2*i+1,2*j-2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1);
else
if(2*j-2<1)
A1(i,j)=w(1,2)*A0(2*i-2,2*j-1)+w(1,3)*A0(2*i-2,2*j)+w(1,4)*A0(2*i-2,2*j+1)+w(1,5)*A0(2*i-2,2*j+2)+w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(2,5)*A0(2*i-1,2*j+2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(3,5)*A0(2*i,2*j+2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1)+w(4,5)*A0(2*i+1,2*j+2)+w(5,2)*A0(2*i+2,2*j-1)+w(5,3)*A0(2*i+2,2*j)+w(5,4)*A0(2*i+2,2*j+1)+w(5,5)*A0(2*i+2,2*j+2);
else
if(2*i-2<1)
A1(i,j)=w(2,1)*A0(2*i-1,2*j-2)+w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(2,5)*A0(2*i-1,2*j+2)+w(3,1)*A0(2*i,2*j-2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(3,5)*A0(2*i,2*j+2)+w(4,1)*A0(2*i+1,2*j-2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1)+w(4,5)*A0(2*i+1,2*j+2)+w(5,1)*A0(2*i+2,2*j-2)+w(5,2)*A0(2*i+2,2*j-1)+w(5,3)*A0(2*i+2,2*j)+w(5,4)*A0(2*i+2,2*j+1)+w(5,5)*A0(2*i+2,2*j+2);
else
if(2*i+2>m0)
A1(i,j)=w(1,1)*A0(2*i-2,2*j-2)+w(1,2)*A0(2*i-2,2*j-1)+w(1,3)*A0(2*i-2,2*j)+w(1,4)*A0(2*i-2,2*j+1)+w(1,5)*A0(2*i-2,2*j+2)+w(2,1)*A0(2*i-1,2*j-2)+w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(2,5)*A0(2*i-1,2*j+2)+w(3,1)*A0(2*i,2*j-2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(3,5)*A0(2*i,2*j+2)+w(4,1)*A0(2*i+1,2*j-2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1)+w(4,5)*A0(2*i+1,2*j+2);
else
if(2*j+2>n0)
A1(i,j)=w(1,1)*A0(2*i-2,2*j-2)+w(1,2)*A0(2*i-2,2*j-1)+w(1,3)*A0(2*i-2,2*j)+w(1,4)*A0(2*i-2,2*j+1)+w(2,1)*A0(2*i-1,2*j-2)+w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(3,1)*A0(2*i,2*j-2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(4,1)*A0(2*i+1,2*j-2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1)+w(5,1)*A0(2*i+2,2*j-2)+w(5,2)*A0(2*i+2,2*j-1)+w(5,3)*A0(2*i+2,2*j)+w(5,4)*A0(2*i+2,2*j+1);
else
A1(i,j)=w(1,1)*A0(2*i-2,2*j-2)+w(1,2)*A0(2*i-2,2*j-1)+w(1,3)*A0(2*i-2,2*j)+w(1,4)*A0(2*i-2,2*j+1)+w(1,5)*A0(2*i-2,2*j+2)+w(2,1)*A0(2*i-1,2*j-2)+w(2,2)*A0(2*i-1,2*j-1)+w(2,3)*A0(2*i-1,2*j)+w(2,4)*A0(2*i-1,2*j+1)+w(2,5)*A0(2*i-1,2*j+2)+w(3,1)*A0(2*i,2*j-2)+w(3,2)*A0(2*i,2*j-1)+w(3,3)*A0(2*i,2*j)+w(3,4)*A0(2*i,2*j+1)+w(3,5)*A0(2*i,2*j+2)+w(4,1)*A0(2*i+1,2*j-2)+w(4,2)*A0(2*i+1,2*j-1)+w(4,3)*A0(2*i+1,2*j)+w(4,4)*A0(2*i+1,2*j+1)+w(4,5)*A0(2*i+1,2*j+2)+w(5,1)*A0(2*i+2,2*j-2)+w(5,2)*A0(2*i+2,2*j-1)+w(5,3)*A0(2*i+2,2*j)+w(5,4)*A0(2*i+2,2*j+1)+w(5,5)*A0(2*i+2,2*j+2);
end
end
end
end
end
end
end
end
end
end
A1=uint8(A1);
这是第0阶和第1阶 上面太难写了 编成myfilter.m文件 直接继续得到第234阶 结果:
A0=imread('F:\fisheye\AA.jpg');
>> A0=rgb2gray(A0);
>> A1=myfilter(A0);
A2=myfilter(A1);
A3=myfilter(A2);
>> A4=myfilter(A3);
>> A1=uint8(A1);
>> A2=uint8(A2);
>> A3=uint8(A3);
>> A4=uint8(A4);
对原图BB也这样:
2,由高斯塔生成拉普拉斯塔 插值扩大相减 这步我先用imresize看看行不行
a4=A4;
[m3,n3]=size(A3);
A4=imresize(A4,[m3 n3]);
a3=A3-A4;
[m2,n2]=size(A2);
A3=imresize(A3,[m2 n2]);
a2=A2-A3;
[m1,n1]=size(A1);
A2=imresize(A2,[m1 n1]);
a1=A1-A2;
[m0,n0]=size(A0);
A1=imresize(A1,[m0 n0]);
a0=A0-A1;
b4=B4;
[m3,n3]=size(B3);
B4=imresize(B4,[m3 n3]);
b3=B3-B4;
[m2,n2]=size(B2);
B3=imresize(B3,[m2 n2]);
b2=B2-B3;
[m1,n1]=size(B1);
B2=imresize(B2,[m1 n1]);
b1=B1-B2;
[m0,n0]=size(B0);
B1=imresize(B1,[m0 n0]);
b0=B0-B1;
%开始融合
c0=imread('F:\fisheye\CC.jpg');
c1=imread('F:\fisheye\src3gaussian1.jpg');
c2=imread('F:\fisheye\src3gaussian2.jpg');
c3=imread('F:\fisheye\src3gaussian3.jpg');
c4=imread('F:\fisheye\src3gaussian4.jpg');
c0=rgb2gray(c0);
c1=rgb2gray(c1);
c2=rgb2gray(c2);
c3=rgb2gray(c3);
c4=rgb2gray(c4);
[m0,n0]=size(a0);
DD0=zeros(m0,n0);
for i=1:m0
for j=1:n0
DD0(i,j)=c0(i,j)*a0(i,j)+(255-c0(i,j))*b0(i,j);
%%DD1(i,j)=CC(i,j)*a1(i,j)+(1-CC(i,j))*b1(i,j);这句应该是错的 不能实打实的按照论文里用1 一边黑0 一边白所以应该是255啊
end
end
DD0=uint8(DD0);
[m1,n1]=size(a1);
DD1=zeros(m1,n1);
for i=1:m1
for j=1:n1
DD1(i,j)=c1(i,j)*a1(i,j)+(255-c1(i,j))*b1(i,j);
end
end
DD1=uint8(DD1);
[m2,n2]=size(a2);
DD2=zeros(m2,n2);
for i=1:m2
for j=1:n2
DD2(i,j)=c2(i,j)*a2(i,j)+(255-c2(i,j))*b2(i,j);
end
end
DD2=uint8(DD2);
[m3,n3]=size(a3);
DD3=zeros(m3,n3);
for i=1:m3
for j=1:n3
DD3(i,j)=c3(i,j)*a3(i,j)+(255-c3(i,j))*b3(i,j);
end
end
DD3=uint8(DD3);
[m4,n4]=size(a4);
DD4=zeros(m4,n4);
for i=1:m4
for j=1:n4
DD4(i,j)=c4(i,j)*a4(i,j)+(255-c4(i,j))*b4(i,j);
end
end
DD4=uint8(DD4);
结果:
这个鬼样!!!!硬着头皮继续让它们插值扩大然后每一阶相加,结果:
%相加
[m3,n3]=size(DD3);
DD4=imresize(DD4,[m3 n3],'bilinear');
D=DD4+DD3;
[m2,n2]=size(DD2);
D=imresize(D,[m2 n2],'bilinear');
D=D+DD2;
[m1,n1]=size(DD1);
D=imresize(D,[m1 n1],'bilinear');
D=D+DD1;
[m0,n0]=size(DD0);
D=imresize(D,[m0 n0],'bilinear');
D=D+DD0;
D=uint8(D);
结果:晕死了!!!!!!!!!!!!还是这鬼样子!!!烦躁
用imresize不行 于是按照论文里的核函数进行插值放大:
function AA4=chazhi(A4,A3)
%都是灰度图 将A4按照论文里w的5x5模板插值放大到A3大小 得到AA4
[m3,n3]=size(A3);
AA4=zeros(m3,n3);
[m4,n4]=size(A4);
w=[1/256,4/256,6/256,4/256,1/256;4/256,16/256,24/256,16/256,4/256;6/256,24/256,36/256,24/256,6/256;4/256,16/256,24/256,16/256,4/256;1/256,4/256,6/256,4/256,1/256];
for i=1:m3
for j=1:n3
for m=1:5
for n=1:5
x=round((i+m-3)/2);
y=round((j+n-3)/2);
x=max(min(x,m4),1);
y=max(min(y,n4),1);
if(x<1||y<1||x>m4||y>n4)
continue;
else
AA4(i,j)=AA4(i,j)+w(m,n)*A4(x,y);
end
end
end
AA4(i,j)=4*AA4(i,j);
end
end
%imshow(AA4,[]);
编成这个m文件 但这样得到的是double类型 如果加上AA4=uint8(AA4);那么出来又不对 所以我干脆把所有的都变成double后面才能相减 如果一个uint8一个double减不了
%按照核函数进行插值 %计算得到拉普拉斯金字塔
a4=double(A4);
AA4=chazhi(A4,A3);
AA3=double(A3);
a3=AA3-AA4;
AA3=chazhi(A3,A2);
AA2=double(A2);
a2=AA2-AA3;
AA2=chazhi(A2,A1);
AA1=double(A1);
a1=AA1-AA2;
AA1=chazhi(A1,A0);
AA0=double(A0);
a0=AA0-AA1;
b4=double(B4);
BB4=chazhi(B4,B3);
BB3=double(B3);
b3=BB3-BB4;
BB3=chazhi(B3,B2);
BB2=double(B2);
b2=BB2-BB3;
BB2=chazhi(B2,B1);
BB1=double(B1);
b1=BB1-BB2;
BB1=chazhi(B1,B0);
BB0=double(B0);
b0=BB0-BB1;
得到AA、BB的五阶拉普拉斯塔 用imshow(b0,[ ])才显示出来 结果有些怪:
这怎么不像是拉普拉斯金字塔 可是实在是按照论文那样子编的啊 看融合后会怎样:
c0=imread('F:\fisheye\CC.jpg');
c0=rgb2gray(c0);
c1=myfilter(c0);
c2=myfilter(c1);
c3=myfilter(c2);
c4=myfilter(c3);
c0=double(c0);
c1=double(c1);
c2=double(c2);
c3=double(c3);
c4=double(c4);
[m0,n0]=size(a0);
DD0=zeros(m0,n0);
for i=1:m0
for j=1:n0
DD0(i,j)=c0(i,j)*a0(i,j)+(255-c0(i,j))*b0(i,j);
DD0(i,j)=DD0(i,j)/255;
end
end
>> [m1,n1]=size(a1);
DD1=zeros(m1,n1);
for i=1:m1
for j=1:n1
DD1(i,j)=c1(i,j)*a1(i,j)+(255-c1(i,j))*b1(i,j);
DD1(i,j)=DD1(i,j)/255;
end
end
>> [m2,n2]=size(a2);
DD2=zeros(m2,n2);
for i=1:m2
for j=1:n2
DD2(i,j)=c2(i,j)*a2(i,j)+(255-c2(i,j))*b2(i,j);
DD2(i,j)=DD2(i,j)/255;
end
end
>> [m3,n3]=size(a3);
DD3=zeros(m3,n3);
for i=1:m3
for j=1:n3
DD3(i,j)=c3(i,j)*a3(i,j)+(255-c3(i,j))*b3(i,j);
DD3(i,j)=DD3(i,j)/255;
end
end
>> [m4,n4]=size(a4);
DD4=zeros(m4,n4);
for i=1:m4
for j=1:n4
DD4(i,j)=c4(i,j)*a4(i,j)+(255-c4(i,j))*b4(i,j);
DD4(i,j)=DD4(i,j)/255;
end
end
这是融合后的 很诡异 是不是开始插值时不该全部转化成double
好奇怪 当我在插值时加上uint8时 下一层的减去插值后的上一层 出来却是个黑屏 可是我查看每点的像素值 明明不相等啊:
AA3
AA3 =
Columns 1 through 13
65 68 84 83 78 70 68 67 69 75 100 147 177
73 94 111 104 86 73 71 70 72 81 105 148 175
81 102 127 107 90 74 71 74 76 78 97 118 132
78 92 103 95 78 69 73 80 84 78 82 86 96
54 63 74 71 66 63 69 77 81 75 75 76 85
54 59 63 63 58 60 64 67 67 67 69 73 80
56 57 60 55 54 54 58 61 67 72 70 75 82
49 53 55 47 44 51 54 51 57 60 65 68 70
39 45 46 44 38 42 48 49 48 49 54 75 98
55 60 61 63 65 63 67 66 68 69 75 92 122
69 79 77 81 84 82 85 89 96 101 95 89 89
86 93 95 98 103 109 113 118 122 128 126 125 126
99 109 110 114 119 119 121 120 122 125 125 126 127
87 94 95 96 100 102 102 104 109 110 112 114 115
73 80 81 83 86 88 91 94 96 98 100 102 106
AA4
AA4 =
Columns 1 through 13
255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255
248 252 255 255 255 255 255 255 255 255 255 255 255
220 224 232 236 236 240 244 248 255 255 255 255 255
212 212 216 216 220 224 232 240 248 255 255 255 255
204 208 212 216 220 224 236 248 255 255 255 255 255
212 220 232 244 244 255 255 255 255 255 255 255 255
240 252 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255 255 255 255 255 255
即使是这样 那减出来也不该是个全黑屏啊
抛开论文 重新看大叔传给我的http://www.360doc.com/content/15/1103/17/27378135_510480683.shtml#细看了这个OPENCV的程序 首先实现了下 这只是举个例子 并不是讲最佳缝合线+多分辨率拼接 只是一半一半这样融合的简单例子 是对的 对照着分析之前自己写的 思考了一些 重新写:
A0=imread('F:\fisheye\AA.jpg');
[m0,n0,k0]=size(A0);
A1=imresize(A0,[m0/2 n0/2],'bilinear');
AA0=imresize(A1,[m0,n0],'bilinear');
a0=A0-AA0;
[m1,n1,k1]=size(A1);
A2=imresize(A1,[m1/2 n1/2],'bilinear');
AA1=imresize(A2,[m1,n1],'bilinear');
a1=A1-AA1;
[m2,n2,k2]=size(A2);
A3=imresize(A2,[m2/2 n2/2],'bilinear');
AA2=imresize(A3,[m2,n2],'bilinear');
a2=A2-AA2;
[m3,n3,k3]=size(A3);
A4=imresize(A3,[m3/2 n3/2],'bilinear');
AA3=imresize(A4,[m3,n3],'bilinear');
a3=A3-AA3;
[m4,n4,k4]=size(A4);
A5=imresize(A4,[m4/2 n4/2],'bilinear');
AA4=imresize(A5,[m4,n4],'bilinear');
a4=A4-AA4;
B0=imread('F:\fisheye\BB.jpg');
[m0,n0,k0]=size(B0);
B1=imresize(B0,[m0/2 n0/2],'bilinear');
BB0=imresize(B1,[m0,n0],'bilinear');
b0=B0-BB0;
[m1,n1,k1]=size(B1);
B2=imresize(B1,[m1/2 n1/2],'bilinear');
BB1=imresize(B2,[m1,n1],'bilinear');
b1=B1-BB1;
[m2,n2,k2]=size(B2);
B3=imresize(B2,[m2/2 n2/2],'bilinear');
BB2=imresize(B3,[m2,n2],'bilinear');
b2=B2-BB2;
[m3,n3,k3]=size(B3);
B4=imresize(B3,[m3/2 n3/2],'bilinear');
BB3=imresize(B4,[m3,n3],'bilinear');
b3=B3-BB3;
[m4,n4,k4]=size(B4);
B5=imresize(B4,[m4/2 n4/2],'bilinear');
BB4=imresize(B5,[m4,n4],'bilinear');
b4=B4-BB4;
%上面得到了两幅图的laplacian金字塔
%下面是用OPENCV求得的模板C的gaussian金字塔
c0=imread('F:\fisheye\CC.jpg');
[m0,n0,k0]=size(c0);
c1=imresize(c0,[m0/2 n0/2],'bilinear');
[m1,n1,k1]=size(c1);
c2=imresize(c1,[m1/2 n1/2],'bilinear');
[m2,n2,k2]=size(c2);
c3=imresize(c2,[m2/2 n2/2],'bilinear');
[m3,n3,k3]=size(c3);
c4=imresize(c3,[m3/2 n3/2],'bilinear');
%每一层融合
[m0,n0,k0]=size(a0);
DD0=zeros(m0,n0,k0);
for i=1:m0
for j=1:n0
DD0(i,j,1)=(c0(i,j,1)*a0(i,j,1)+(255-c0(i,j,1))*b0(i,j,1))/255;
DD0(i,j,2)=(c0(i,j,2)*a0(i,j,2)+(255-c0(i,j,2))*b0(i,j,2))/255;
DD0(i,j,3)=(c0(i,j,3)*a0(i,j,3)+(255-c0(i,j,3))*b0(i,j,3))/255;
end
end
DD0=uint8(DD0);
[m1,n1,k1]=size(a1);
DD1=zeros(m1,n1,k1);
for i=1:m1
for j=1:n1
DD1(i,j,1)=(c1(i,j,1)*a1(i,j,1)+(255-c1(i,j,1))*b1(i,j,1))/255;
DD1(i,j,2)=(c1(i,j,2)*a1(i,j,2)+(255-c1(i,j,2))*b1(i,j,2))/255;
DD1(i,j,3)=(c1(i,j,3)*a1(i,j,3)+(255-c1(i,j,3))*b1(i,j,3))/255;
end
end
DD1=uint8(DD1);
[m2,n2,k2]=size(a2);
DD2=zeros(m2,n2,k2);
for i=1:m2
for j=1:n2
DD2(i,j,1)=(c2(i,j,1)*a2(i,j,1)+(255-c2(i,j,1))*b2(i,j,1))/255;
DD2(i,j,2)=(c2(i,j,2)*a2(i,j,2)+(255-c2(i,j,2))*b2(i,j,2))/255;
DD2(i,j,3)=(c2(i,j,3)*a2(i,j,3)+(255-c2(i,j,3))*b2(i,j,3))/255;
end
end
DD2=uint8(DD2);
[m3,n3,k3]=size(a3);
DD3=zeros(m3,n3,k3);
for i=1:m3
for j=1:n3
DD3(i,j,1)=(c3(i,j,1)*a3(i,j,1)+(255-c3(i,j,1))*b3(i,j,1))/255;
DD3(i,j,2)=(c3(i,j,2)*a3(i,j,2)+(255-c3(i,j,2))*b3(i,j,2))/255;
DD3(i,j,3)=(c3(i,j,3)*a3(i,j,3)+(255-c3(i,j,3))*b3(i,j,3))/255;
end
end
DD3=uint8(DD3);
[m4,n4,k4]=size(a4);
DD4=zeros(m4,n4,k4);
for i=1:m4
for j=1:n4
DD4(i,j,1)=(c4(i,j,1)*a4(i,j,1)+(255-c4(i,j,1))*b4(i,j,1))/255;
DD4(i,j,2)=(c4(i,j,2)*a4(i,j,2)+(255-c4(i,j,2))*b4(i,j,2))/255;
DD4(i,j,3)=(c4(i,j,3)*a4(i,j,3)+(255-c4(i,j,3))*b4(i,j,3))/255;
end
end
DD4=uint8(DD4);
[m3,n3,k3]=size(DD3);
DD4=imresize(DD4,[m3 n3],'bilinear');
D=DD4+DD3;
[m2,n2,k2]=size(DD2);
D=imresize(D,[m2 n2],'bilinear');
D=D+DD2;
[m1,n1,k1]=size(DD1);
D=imresize(D,[m1 n1],'bilinear');
D=D+DD1;
[m0,n0,k0]=size(DD0);
D=imresize(D,[m0 n0],'bilinear');
D=D+DD0;
D=uint8(D);
可是这样写得到的D还是个黑屏啊 思考了很久 这几天写的 其实无论是用OPENCV的pyrUp、pyrDown直接得到的高斯金字塔 还是后面按论文编的 包括后面的几步 无论是直接用MATLAB的函数 还是自己写的,,,想了想,,,应该是问题出在数据类型那里,,,就像http://www.360doc.com/content/15/1103/17/27378135_510480683.shtml#将原图两幅cvconvertTo那里 我不知道它是转化成什么类型 其实是每个点每个通道的值除以了255 在我看来就像归一化 可是当我真正用MATLAB也先把它做归一化时 不对!我想想想想 搞了几天了 哎
直接在OPENCV上用那个编:
#include "opencv2/opencv.hpp"
using namespace cv;
class LaplacianBlending {
private:
Mat_<Vec3f> left;
Mat_<Vec3f> right;
Mat_<float> blendMask;
vector<Mat_<Vec3f> > leftLapPyr,rightLapPyr,resultLapPyr;//Laplacian Pyramids
Mat leftHighestLevel, rightHighestLevel, resultHighestLevel;
vector<Mat_<Vec3f> > maskGaussianPyramid; //masks are 3-channels for easier multiplication with RGB
int levels;
void buildPyramids() {
buildLaplacianPyramid(left,leftLapPyr,leftHighestLevel);
buildLaplacianPyramid(right,rightLapPyr,rightHighestLevel);
buildGaussianPyramid();
}
void buildGaussianPyramid() {//金字塔内容为每一层的掩模
assert(leftLapPyr.size()>0);
maskGaussianPyramid.clear();
Mat currentImg;
cvtColor(blendMask, currentImg, CV_GRAY2BGR);//store color img of blend mask into maskGaussianPyramid
maskGaussianPyramid.push_back(currentImg); //0-level
currentImg = blendMask;
for (int l=1; l<levels+1; l++) {
Mat _down;
if (leftLapPyr.size()>l)
pyrDown(currentImg, _down, leftLapPyr[l].size());
else
pyrDown(currentImg, _down, leftHighestLevel.size()); //lowest level
Mat down;
cvtColor(_down, down, CV_GRAY2BGR);
maskGaussianPyramid.push_back(down);//add color blend mask into mask Pyramid
currentImg = _down;
}
}
void buildLaplacianPyramid(const Mat& img, vector<Mat_<Vec3f> >& lapPyr, Mat& HighestLevel) {
lapPyr.clear();
Mat currentImg = img;
for (int l=0; l<levels; l++) {
Mat down,up;
pyrDown(currentImg, down);
pyrUp(down, up,currentImg.size());
Mat lap = currentImg - up;
lapPyr.push_back(lap);
currentImg = down;
}
currentImg.copyTo(HighestLevel);
}
//void blendLapPyrs() {
//获得每层金字塔中直接用左右两图Laplacian变换拼成的图像resultLapPyr
//resultHighestLevel = leftHighestLevel.mul(maskGaussianPyramid.back()) +
//rightHighestLevel.mul(Scalar(1.0,1.0,1.0) - maskGaussianPyramid.back());
/// for (int l=0; l<levels; l++) {
//Mat A = leftLapPyr[l].mul(maskGaussianPyramid[l]);
//Mat antiMask = Scalar(1.0,1.0,1.0) - maskGaussianPyramid[l];
//Mat B = rightLapPyr[l].mul(antiMask);
//Mat_<Vec3f> blendedLevel = A + B;
//resultLapPyr.push_back(blendedLevel);
//}
//}
//上面这个得到每一阶的融合图 好像要改动
void blendLapPyrs()
{
resultHighestLevel = leftHighestLevel.mul(maskGaussianPyramid.back()) +rightHighestLevel.mul(Scalar(1.0,1.0,1.0) - maskGaussianPyramid.back());
//以上得到的是最高阶的上一阶的融合图
for (int l=0; l<levels; l++)
{
Mat A = leftLapPyr[l].mul(maskGaussianPyramid[l]);
Mat antiMask = Scalar(1.0,1.0,1.0) - maskGaussianPyramid[l];
Mat B = rightLapPyr[l].mul(antiMask);
Mat_<Vec3f> blendedLevel = A + B;
resultLapPyr.push_back(blendedLevel);
}
}
Mat_<Vec3f> reconstructImgFromLapPyramid() {
//将左右laplacian图像拼成的resultLapPyr金字塔中每一层
//从上到下插值放大并相加,即得blend图像结果
Mat currentImg = resultHighestLevel;
for (int l=levels-1; l>=0; l--) {
Mat up;
pyrUp(currentImg, up, resultLapPyr[l].size());
currentImg = up + resultLapPyr[l];
}
return currentImg;
}
public:
LaplacianBlending(const Mat_<Vec3f>& _left, const Mat_<Vec3f>& _right, const Mat_<float>& _blendMask, int _levels)://construct function, used in LaplacianBlending lb(l,r,m,4);
left(_left),right(_right),blendMask(_blendMask),levels(_levels)
{
assert(_left.size() == _right.size());
assert(_left.size() == _blendMask.size());
buildPyramids(); //construct Laplacian Pyramid and Gaussian Pyramid
blendLapPyrs(); //blend left & right Pyramids into one Pyramid
};
Mat_<Vec3f> blend() {
return reconstructImgFromLapPyramid();//reconstruct Image from Laplacian Pyramid
}
};
Mat_<Vec3f> LaplacianBlend(const Mat_<Vec3f>& l, const Mat_<Vec3f>& r, const Mat_<float>& m) {
LaplacianBlending lb(l,r,m,5);
return lb.blend();
}
int main()
{
Mat l8u = imread("left.jpg");
Mat r8u = imread("right.jpg");
imshow("left",l8u);
imshow("right",r8u);
Mat_<Vec3f> l;
l8u.convertTo(l,CV_32F,1.0/255.0);//Vec3f表示有三个通道,即 l[row][column][depth]
Mat_<Vec3f> r;
r8u.convertTo(r,CV_32F,1.0/255.0);//不是都乘以1/255的意思 不是归一化 是转换成什么类型呢?
//Mat_<float> m(l.rows,l.cols,0.0); //将m全部赋值为0
//m(Range::all(),Range(0,m.cols/2)) = 1.0; //取m全部行&[0,m.cols/2]列,赋值为1.0
//上面这个模板m要改 改成最佳缝合线得到的结果C的样子
Mat_<float> m(l.rows,l.cols,0.0);
Mat C=imread("CC.jpg");
for(int i=0;i<l.rows;i++)
{
for(int j=0;j<l.cols;j++)
{
if(C.at<Vec3b>(i,j)[0]!=0&&C.at<Vec3b>(i,j)[1]!=0&&C.at<Vec3b>(i,j)[2]!=0) // 因为我要的只是位置
m(i,j)=1.0;
}
}
Mat_<Vec3f> blend = LaplacianBlend(l, r, m);
imshow("blended",blend);
waitKey(0);
return 0;
}
结果:
得到的融合图是按上一篇的最佳缝合线进行的 但是为什么内容 缝合线左右的内容不对 可是明明上面程序的原理是正确的 我那样改模板也对啊 不然不会出现这个结果 可以对比上幅图 证明缝合线是加进去了 可是两边的内容。。。?
我知道我之前编的几种 各种试都是错的 原因在哪里了 是因为我第一步就错了 填充图那里 我是按照之前那篇论文编的 都用的replicate填充 其实应该用0黑色来填充 然后模板是左边填0右边填255 所以我第一步就是错的!!后面即使是那样编的 那我也会得到错的!太傻了!受不了
所以现在重来
重来重来全部重来!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
先选定两幅曝光差异很大的图:
和
然后送到OPENCV里进行特征点检测匹配得到 匹配对坐标 存为txt 然后用MATLAB读取 计算出H矩阵 然后进行H矩阵变换 得到:
在MATLAB里试下我之前编的那个渐入渐出融合 效果:
可以看到渐入渐出解决不了重影以及曝光差异
最佳缝合线算法 在MATLAB里找到最佳缝合路径:
可以很清晰的看到选出的最佳缝合线 没有了渐入渐出那么强烈的鬼影 接下来就是多分辨率算法消除曝光差异 :
第一步:是将原图都扩大到上面这幅这么大 还有一个模板也扩大到这么大 扩充部分用0填充 在MATLAB上做
D=bestlinefusion(A,B);
[m,n,k]=size(D);
E=uint8(zeros(m,n,k));
[ma,na,ka]=size(A);
for i=1:ma
for j=1:na
E(i,j,1)=A(i,j,1);
E(i,j,2)=A(i,j,2);
E(i,j,3)=A(i,j,3);
end
end
F=uint8(zeros(m,n,k));
[mb,nb,kb]=size(B);
L=n-nb+1;
for i=1:mb
for j=L:n
F(i,j,1)=B(i,j-(n-nb),1);
F(i,j,2)=B(i,j-(n-nb),2);
F(i,j,3)=B(i,j-(n-nb),3);
end
end
我觉得是这样填充的 还有模板也要填充得到模板F:
然后再在OPENCV里面用我改的那个多分辨率融合的程序 结果:
上一次被吃掉的重叠部分又出来了 可是两边又没了 难道模板错了 因为看过的论文里模板说得不一样 有的说左白右黑 有的说左黑右白 我试下左白右黑的情况 结果:
看看看 终于弄出来了 曝光差异分界好像没那么明显了 而且是按照最佳缝合线来的 就是这样子的 终于弄出来了 太开心了 那些论文真是的 说又不说清楚有的好像故意留点什么似的 填充又不说怎么填充 好像涉及到具体的编程时会考虑的问题 那些作者就避而不谈一样 真是的 有的还说个错的误导编程的人 不过这样有个唯一的好处 就是让你随时保持批判精神自己独立思考 它论文只给出大体思想而已。