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

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

这个图融合处是有重影的

在一个博文《多分辨率拼接算法(继最佳缝合线之后)》中,有一个最佳缝合线的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);
//朋友MR_Radish666 说上句应该是:mypath=path.colRange(minth-1,minth);

//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(l,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);//到大图

效果图:

 



哪个重影已经没有了。

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

先这样吧。

 

  • 7
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 44
    评论
对于最佳缝合线融合算法图像拼接的 Python 实现,我可以提供一些参考资料和代码示例,但具体实现细节需要根据具体情况进行调整和优化。以下是一个基于 OpenCV 库的 Python 实现示例: ```python import cv2 import numpy as np # 读取两张待拼接的图像 img1 = cv2.imread('image1.jpg') img2 = cv2.imread('image2.jpg') # 将两张图像转换为灰度图像 gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY) gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # 使用 SIFT 特征检测器和描述符提取器 sift = cv2.xfeatures2d.SIFT_create() kp1, des1 = sift.detectAndCompute(gray1, None) kp2, des2 = sift.detectAndCompute(gray2, None) # 使用 FLANN 匹配器进行特征点匹配 FLANN_INDEX_KDTREE = 0 index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) search_params = dict(checks=50) flann = cv2.FlannBasedMatcher(index_params, search_params) matches = flann.knnMatch(des1, des2, k=2) # 筛选出最佳匹配点对 good_matches = [] for m, n in matches: if m.distance < 0.7 * n.distance: good_matches.append(m) # 计算图像间的变换矩阵 src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2) M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) # 将第二张图像变换到第一张图像的坐标系中 h, w = gray1.shape warped_img2 = cv2.warpPerspective(img2, M, (w, h)) # 将两张图像进行融合 blend_img = cv2.addWeighted(img1, 0.5, warped_img2, 0.5, 0) # 显示拼接结果 cv2.imshow('Blend Image', blend_img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这段代码实现了基于 SIFT 特征点匹配和 RANSAC 算法的图像拼接,可以将两张图像进行无融合。如果需要更高效的实现,可以考虑使用 GPU 加速或者其他更高级的算法。
评论 44
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值