多图像拼接---最佳缝合融合

前面已经做了亮度调整,和权重融合


这个图融合处是有重影的

在一个博文《多分辨率拼接算法(继最佳缝合线之后)》中,有一个最佳缝合线的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);//到大图
效果图:



哪个重影已经没有了。

这个最佳缝合线好象不是很好,好多地方跑到重合区边界就成一条直线了,接缝就比较明显了

先这样吧。


猜你喜欢

转载自blog.csdn.net/juebai123/article/details/79732731