简单快速的多图像拼接---百图拼接---补充

前面的视频是同一个方向转圈,如果到了一圈相反转,再相反转会怎样呢?

重新拍了一个视频,3圈(右--左--右),用前面的选片工具,选了86张图

接片效果图:


上下没有重合,如果前面有一张没有配好,后面的就全部不重合了。

先来看看一圈的效果:


去掉单图黑边

Mat myimread(string & n)
{
	Mat im=imread(n);
	Mat roi2;
	im(Range(3, im.rows-6), Range(3, im.cols-6)).copyTo(roi2);//消除黑边
	return roi2;

}
用这个函数代替imread:

加上左右融合:

void 融合(Mat & im,Mat &dst,Point2f p)//四边融合
{
	int w=100; //融合宽;
	int c=im.cols,r=im.rows;
	int c2=dst.cols,r2=dst.rows;

	float a;//权重
	int x,y;
	for(int i=0;i<r;i++)
	{
		//左边
		for(int j=0;j<w;j++)
		{
			x=p.x+j;
			y=p.y+i;

			if (dst.at<Vec3b>(y,x)[0]!=0 || dst.at<Vec3b>(y,x)[1]!=0 || dst.at<Vec3b>(y,x)[2]!=0)
			{
				a=1.0-(float)j/w;//权重
				//原图和新图又叠加
				dst.at<Vec3b>(y,x)[0]=a*dst.at<Vec3b>(y,x)[0] + (1.0-a)*im.at<Vec3b>(i,j)[0];
				dst.at<Vec3b>(y,x)[1]=a*dst.at<Vec3b>(y,x)[1] + (1.0-a)*im.at<Vec3b>(i,j)[1];
				dst.at<Vec3b>(y,x)[2]=a*dst.at<Vec3b>(y,x)[2] + (1.0-a)*im.at<Vec3b>(i,j)[2];
			}
			else
			{
				//直接复制
				dst.at<Vec3b>(y,x)[0]=im.at<Vec3b>(i,j)[0];
				dst.at<Vec3b>(y,x)[1]=im.at<Vec3b>(i,j)[1];
				dst.at<Vec3b>(y,x)[2]=im.at<Vec3b>(i,j)[2];
			}
		}
		//右边
		for(int j=c-w;j<c;j++)
		{
			x=p.x+j;
			y=p.y+i;

			if (dst.at<Vec3b>(y,x)[0]!=0 || dst.at<Vec3b>(y,x)[1]!=0 || dst.at<Vec3b>(y,x)[2]!=0)
			{
				a=(float)(j-(c-w))/w;//右边权重
				dst.at<Vec3b>(y,x)[0]=a*dst.at<Vec3b>(y,x)[0] + (1.0-a)*im.at<Vec3b>(i,j)[0];
				dst.at<Vec3b>(y,x)[1]=a*dst.at<Vec3b>(y,x)[1] + (1.0-a)*im.at<Vec3b>(i,j)[1];
				dst.at<Vec3b>(y,x)[2]=a*dst.at<Vec3b>(y,x)[2] + (1.0-a)*im.at<Vec3b>(i,j)[2];
			}
			else
			{
				dst.at<Vec3b>(y,x)[0]=im.at<Vec3b>(i,j)[0];
				dst.at<Vec3b>(y,x)[1]=im.at<Vec3b>(i,j)[1];
				dst.at<Vec3b>(y,x)[2]=im.at<Vec3b>(i,j)[2];
			}
		}
	}
	Mat roi2(dst, Rect(p.x+w, p.y, im.cols-2*w, im.rows));//复制中间部分
        im(Range(0, im.rows), Range(w, im.cols-w)).copyTo(roi2);

}
用这个函数代替复制部分:

效果好一点了,再把亮度校正下(匹配点):

	//计算各图匹配点亮度比例
	vector<float> 比_colors;//比_colors[i]表示第i个图像颜色和第一个图的比值
								//亮度比值,第一个为1,其它相对于第一个
	get亮度比率(image_colors,image_matches ,比_colors);

	//再把所有图像放到一个大图中(拼接)
	for (unsigned int i=0;i<position_da.size ();i++)
	{
		Mat im = myimread(image_names[i]);//读出一个图

		//亮度调整
		im/=比_colors[i];//按比值反向修正

		int x=position_da[i].x-xmin;
		int y=position_da[i].y-ymin;
		//Mat roi2(stitch, Rect(x, y, im.cols, im.rows));
  //      im(Range(0, im.rows), Range(0, im.cols)).copyTo(roi2);
		//加融合+++++++++++++++++++++++++++
		融合(im,stitch,Point2f(x,y));//二边融合

	}

最后二张图已经是第二圈的先把它去掉:


这样就好多了,再调整一下左右图高度,把它对齐:

	前后对齐
	{
		//再计算最小,最大边界
		int xmin=0,xmax=0;
		int ixmin=1,ixmax=1;//最左和最右的位置
		for (unsigned int i=1;i<position_da.size ();i++)
		{
			int ti,ta;
			ti=xmin;ta=xmax;
			xmin=(position_da[i].x<xmin)?position_da[i].x:xmin;
			xmax=(position_da[i].x>xmax)?position_da[i].x:xmax;
			if(ti!=xmin)
				ixmin=i;
			if(ta!=xmax)
				ixmax=i;

		}
		vector<DMatch> m;
		
		match_features1 (image_descriptor[ixmin], image_descriptor[ixmax], m);
		refineMatchesWithHomography( image_keypoints[ixmin], image_keypoints[ixmax],1.0, m   );    

		cout<<"前后匹配数:"<<m.size ()<<endl;
		if(m.size ()>0){

			//得到匹配点坐标
			vector<Point2f> points1, points2;
			int src=ixmin;
			int dis=ixmax;

			get_match_points (image_keypoints[src], image_keypoints[dis] ,m, points1, points2);

			Point2f a = getOffset(points1,points2);
			cout << "前后两个相差:"<<a<< endl;

			//在大图的位置
			//新的位置
			position_s.x=position_da[src].x+a.x;
			position_s.y=position_da[src].y+a.y;
			//差值(新 - 老)
			position_s.x-=position_da[dis].x;
			position_s.y-=position_da[dis].y;
			cout << "位置差值:"<<position_s<< endl;

			//计算平均校正值
			int p=dis-src-1;//中间数;
			float 平均x=position_s.x/p;
			float 平均y=position_s.y/p;
			for (unsigned int j=src+1;j<dis;j++)
			{
				//position_da[j].x+=平均x;
				position_da[j].y+=平均y;
			}
	
		}
	}

这是最终效果,虽然也不是很好,比前面已经好多了。

猜你喜欢

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