前面已经做了亮度调整,和权重融合
这个图融合处是有重影的
在一个博文《多分辨率拼接算法(继最佳缝合线之后)》中,有一个最佳缝合线的matlab的代码,
我把它改成opencv的一个函数bestlinefusion:
//《图像拼接的改进算法》最佳缝合线算法 图像融合 Mat_<Vec3f> bestlinefusion(Mat_<Vec3f> & A,Mat_<Vec3f>& B,int rdata1) //function D=bestlinefusion(A,B,rdata1) { //先根据之前得到的H矩阵计算重叠区域Rect //[H,W,k]=size(A); int H,W; H=A.rows;W=A.cols; //rdata1=-118; //rdata1=fix(-rdata1); rdata1=-rdata1; //L=W+1+rdata1; int L=W+rdata1; //R=W; int R=W; //n=R-L+1; int n=R-L; //计算得到重叠区域的差值图像 其实我不懂计算差值图像干嘛 只要计算重叠区域的大小就好了 为什么还要计算差值图 后面又没用到 //Rect=zeros(H,n); Mat_<float> Rectf=Mat_<float>::zeros(H,n); #define A(x,y) A(x,y)[0] #define B(x,y) B(x,y)[0] //for i=1:H for(int i=0;i<H;i++){ // for j=L:R for(int j=L;j<R;j++){ Rectf(i,j-L+1)=A(i,j)-B(i,j-L+1); //Rectf(i,j-L)=A(i,j)[0]-B(i,j-L+1)[0]; }//end }//end //Rectf=uint8(Rectf);//这句要不要呢? //最终融合图的大小 //rdata1=-118; //rdata2=3; int Y=2*W+rdata1+1; Mat_<Vec3f> D=Mat_<Vec3f>::zeros(H,Y); //放路径的矩阵 Mat_<float> path=Mat_<float>::zeros(H,n); //放强度值 每条路径的强度值strength=color^2+geometry Mat_<float> color=Mat_<float>::zeros(1,n); Mat_<float> geometry=Mat_<float>::zeros(1,n); Mat_<float> strength1=Mat_<float>::zeros(1,n); Mat_<float> strength2=Mat_<float>::zeros(1,n); float Bxdao; float Bydao; float Aydao; float Axdao; //计算第一行即初始化的强度值 //for j=L:R for(int j=L;j<R;j++){ int y=j-L+1; color(y)=A(1,j)-B(1,y); if(y==1){ Bxdao=B(1,y+1)+2*B(2,y+1); Bydao=B(2,y)+2*B(2,y+1); Aydao=2*A(2,j-1)+A(2,j)+2*A(2,j+1); Axdao=A(1,j+1)+2*A(2,j+1)-A(1,j-1)-2*A(2,j-1); geometry(y)=(Axdao-Bxdao)*(Aydao-Bydao); strength1(y)=sqrt(color(y))+geometry(y); path(1,y)=y; continue; }//end if(j==R){ Axdao=A(1,j-1)-2*A(2,j-1); Aydao=2*A(2,j-1)+A(2,j); Bxdao=B(1,y+1)+2*B(2,y+1)-B(1,y-1)-2*B(2,y-1); Bydao=2*B(2,y-1)+B(2,y)+2*B(2,y+1); geometry(y)=(Axdao-Bxdao)*(Aydao-Bydao); strength1(y)=sqrt(color(y))+geometry(y); path(1,y)=y; continue; }//end Axdao=A(1,j+1)+2*A(2,j+1)-A(1,j-1)-2*A(2,j-1); Bxdao=B(1,y+1)+2*B(2,y+1)-B(1,y-1)-2*B(2,y-1); Aydao=2*A(2,j-1)+A(2,j)+2*A(2,j+1); Bydao=2*B(2,y-1)+B(2,y)+2*B(2,y+1); geometry(y)=(Axdao-Bxdao)*(Aydao-Bydao); strength1(y)=sqrt(color(y))+geometry(y); path(1,y)=y; }//end color=Mat_<float>::zeros(1,n); geometry=Mat_<float>::zeros(1,n); float small=0; //开始扩展 向下一行 从第二行到倒数第二行 最后一行单独拿出来 像第一行一样 因为它的结构差值geometry不好算 //for i=2:H-1 for(int i=1;i<H-1;i++){ //先把下一行的强度值全部计算出来 到时候需要比较哪三个就拿出哪三个 //for j=L:R for(int j=L;j<R;j++){ int x=i; int y=j-L+1; color(y)=A(i,j)-B(x,y); if(y==1){ Axdao=2*A(i-1,j+1)+A(i,j+1)+2*A(i+1,j+1)-2*A(i-1,j-1)-A(i,j-1)-2*A(i+1,j-1); Bxdao=2*B(x-1,y+1)+B(x,y+1)+2*B(x+1,y+1); Aydao=-2*A(i-1,j-1)-A(i-1,j)-2*A(i-1,j+1)+2*A(i+1,j-1)+A(i+1,j)+2*A(i+1,j+1); Bydao=-B(x-1,y)-2*B(x-1,y+1)+B(x+1,y)+2*B(x+1,y+1); geometry(y)=(Axdao-Bxdao)*(Aydao-Bydao); strength2(y)=sqrt(color(y))+geometry(y); continue; }//end if(j==R){ Axdao=-2*A(i-1,j-1)-A(i,j-1)-2*A(i+1,j-1); Bxdao=2*B(x-1,y+1)+B(x,y+1)+2*B(x+1,y+1)-2*B(x-1,y-1)-B(x,y-1)-2*B(x+1,y-1); Aydao=-2*A(i-1,j-1)-A(i-1,j)+2*A(i+1,j-1)+A(i+1,j); Bydao=-2*B(x-1,y-1)-B(x-1,y)-2*B(x-1,y+1)+2*B(x+1,y-1)+B(x+1,y)+2*B(x+1,y+1); geometry(y)=(Axdao-Bxdao)*(Aydao-Bydao); strength2(y)=sqrt(color(y))+geometry(y); continue; }//end Axdao=2*A(i-1,j+1)+A(i,j+1)+2*A(i+1,j+1)-2*A(i-1,j-1)-A(i,j-1)-2*A(i+1,j-1); Bxdao=2*B(x-1,y+1)+B(x,y+1)+2*B(x+1,y+1)-2*B(x-1,y-1)-B(x,y-1)-2*B(x+1,y-1); Aydao=-2*A(i-1,j-1)-A(i-1,j)-2*A(i-1,j+1)+2*A(i+1,j-1)+A(i+1,j)+2*A(i+1,j+1); Bydao=-2*B(x-1,y-1)-B(x-1,y)-2*B(x-1,y+1)+2*B(x+1,y-1)+B(x+1,y)+2*B(x+1,y+1); geometry(y)=(Axdao-Bxdao)*(Aydao-Bydao); strength2(y)=sqrt(color(y))+geometry(y); }//end //for j=1:n for(int j=0;j<n;j++){ if(path(i-1,j)==1){ if(strength2(1)<strength2(2)){ strength1(j)=strength1(j)+strength2(1); path(i,j)=1; }else{ strength1(j)=strength1(j)+strength2(2); path(i,j)=2; }//end }else{ if(path(i-1,j)==n){ if(strength2(n-1)<strength2(n)){ strength1(j)=strength1(j)+strength2(n-1); path(i,j)=n-1; }else{ strength1(j)=strength1(j)+strength2(n); path(i,j)=n; }//end }else{ if(strength2(path(i-1,j)-1)<strength2(path(i-1,j))){ if(strength2(path(i-1,j)-1)<strength2(path(i-1,j)+1)){ small=strength2(path(i-1,j)-1); path(i,j)=path(i-1,j)-1; }else{ small=strength2(path(i-1,j)+1); path(i,j)=path(i-1,j)+1; }//end }else{ if(strength2(path(i-1,j))<strength2(path(i-1,j)+1)){ small=strength2(path(i-1,j)); path(i,j)=path(i-1,j); }else{ small=strength2(path(i-1,j)+1); path(i,j)=path(i-1,j)+1; }//end }//end strength1(j)=strength1(j)+small; }//end }//end small=0; }//end strength2=Mat_<float>::zeros(1,n); color=Mat_<float>::zeros(1,n); geometry=Mat_<float>::zeros(1,n); //if (0==(i%10))cout<<i<<endl;//disp(i);end; }//end //cout<<"color:"<<color.rows<<"'"<<color.cols<<endl; //单独计算最后一行 { int i=H-1; //for j=L:R //cout<<"L,R:"<<L<<"'"<<R<<endl; for(int j=L;j<R;j++){ int x=i; int y=j-L+1; //cout<<"i:"<<i<<endl; //cout<<"j:"<<j<<endl; //cout<<"x:"<<x<<endl; //cout<<"y:"<<y<<endl; color(y)=A(i,j)-B(x,y); if(y==1){ Axdao=2*A(i-1,j+1)+A(i,j+1)-2*A(i-1,j-1)-A(i,j-1); Aydao=-2*A(i-1,j-1)-A(i-1,j)-2*A(i-1,j+1); Bxdao=2*B(x-1,y+1)+B(x,y+1); Bydao=-B(x-1,y)-2*B(x-1,y+1); continue; }//end if(j==R){ Bxdao=2*B(x-1,y+1)+B(x,y+1)-2*B(x-1,y-1)-B(x,y-1); Bydao=-2*B(x-1,y-1)-B(x-1,y)-2*B(x-1,y+1); Axdao=-2*A(i-1,j-1)-A(i,j-1); Aydao=-2*A(i-1,j-1)-A(i-1,j); continue; }//end Axdao=2*A(i-1,j+1)+A(i,j+1)-2*A(i-1,j-1)-A(i,j-1); Bxdao=2*B(x-1,y+1)+B(x,y+1)-2*B(x-1,y-1)-B(x,y-1); Aydao=-2*A(i-1,j-1)-A(i-1,j)-2*A(i-1,j+1); Bydao=-2*B(x-1,y-1)-B(x-1,y)-2*B(x-1,y+1); geometry(y)=(Axdao-Bxdao)*(Aydao-Bydao); strength2(y)=sqrt(color(y))+geometry(y); }//end //for j=1:n for(int j=0;j<n;j++){ if(path(i-1,j)==1){ if(strength2(1)<strength2(2)){ strength1(j)=strength1(j)+strength2(1); path(i,j)=1; }else{ strength1(j)=strength1(j)+strength2(2); path(i,j)=2; }//end }else{ if(path(i-1,j)==n){ if(strength2(n-1)<strength2(n)){ strength1(j)=strength1(j)+strength2(n-1); path(i,j)=n-1; }else{ strength1(j)=strength1(j)+strength2(n); path(i,j)=n; }//end }else{ if(strength2(path(i-1,j)-1)<strength2(path(i-1,j))){ if(strength2(path(i-1,j)-1)<strength2(path(i-1,j)+1)){ small=strength2(path(i-1,j)-1); path(i,j)=path(i-1,j)-1; }else{ small=strength2(path(i-1,j)+1); path(i,j)=path(i-1,j)+1; }//end }else{ if(strength2(path(i-1,j))<strength2(path(i-1,j)+1)){ small=strength2(path(i-1,j)); path(i,j)=path(i-1,j); }else{ small=strength2(path(i-1,j)+1); path(i,j)=path(i-1,j)+1; }//end }//end strength1(j)=strength1(j)+small; }//end }//end small=0; }//end } //比较strength1里放的每条路径的强度值的总和 谁最小 就选path中对应的那一列的路径 //[minzhi,minth]=min(strength1); float minzhi=strength1(0); int minth=0; for(int i=1;i<n;i++){ if(minzhi>strength1(i)){ minzhi=strength1(i); minth=i; } } Mat_<float> mypath=Mat_<float>::zeros(H,1); //mypath=path(:,minth); mypath=path.colRange(n-1,n); //cout<<"一条最小路径:"<<endl<<mypath<<endl; #undef A #define A(x,y,i) A(x,y)[i-1] #undef B #define B(x,y,i) B(x,y)[i-1] #define D(x,y,i) D(x,y)[i-1] //mypath放的就是最佳缝合线选出的路径 这条路径坐标是参考图A 右边是目标图B //for i=1:H for(int i=0;i<H;i++){ for(int j=0;j<mypath(i)+L;j++){ D(i,j,1)=A(i,j,1); D(i,j,2)=A(i,j,2); D(i,j,3)=A(i,j,3); }//end for(int j=mypath(i)+L;j<Y;j++){ int x=i; int y=j-L+1; //if( y>W || x>H )continue;//end D(i,j,1)=B(x,y,1); D(i,j,2)=B(x,y,2); D(i,j,3)=B(x,y,3); }//end }//end //D=uint8(D); // 画最佳缝合线 L=W+1+rdata1; //figure;imshow(D) //hold on; for(int i=0;i<H;i++){ D(i,L+mypath(i),1)=1.0; D(i,L+mypath(i),2)=1.0; D(i,L+mypath(i),3)=1.0; }//end //hold off; //Mat roi2; //D.convertTo(roi2,CV_8U,255); //imwrite("line.jpg",roi2); return D; #undef A #undef B #undef D }然后调用这个函数,调用前
先准备好,左、右图,(由于这个函数只能左向右拼,如果要向其它方向拼,可能要先翻转图像):
//左图 Mat_<Vec3f> l; int x=p.x-(im.cols-w); cout<<"x="<<x<<endl; Mat l8u(dst, Rect(x, p.y, im.cols, im.rows));//左图 l8u2.convertTo(l,CV_32F,1.0/255.0);//Vec3f表示有三个通道,即 l[row][column][depth] //imshow("l",l); //右图 Mat_<Vec3f> r; im.convertTo(r,CV_32F,1.0/255.0); //缝合图 Mat_<Vec3f> bm=bestlinefusion(l2,r,w); //imshow("最佳缝合线",bm); Mat src; bm.convertTo(src,CV_8U,255); Mat dstroi(dst, Rect(p.x, p.y, im.cols, im.rows));//大图中的右图位置 Rect r0(im.cols-w,0,im.cols,im.rows); // 只取右图位置 src(r0).convertTo(dstroi, dstroi.type(), 1,0); // 到大图
再把该文中的多分辨率拼接类保存为cpp放在我们的程序中
#include"v2.cpp"//多频段图像融合 类和上面的函数类似,准备左、右、掩码图,调用
Mat_<Vec3f> blend = LaplacianBlend(l, r, m);//金字塔融合 blend.convertTo(dstroi,CV_8U,255);//到大图效果图:
哪个重影已经没有了。
这个最佳缝合线好象不是很好,好多地方跑到重合区边界就成一条直线了,接缝就比较明显了
先这样吧。