由于项目需要,其中一部分功能是需要实现360度旋转相机的图像拼接显示功能,于是使用opencv来将其实现。
由于旋转相机,可以将其看成只有x和y方向上的平移,其中x方向重叠像素比较多即平移比较多,y方向只有少量平移。
如上图所示:待拼接的图像分辨率为800*600;只在xy上有平移。
步骤一:通过画图软件打开查看像素,大概估计出重叠区域大小。
如右边图所示,我选择的是左帧的A区域,和右帧的B区域。A为120*600,B为100*580。
步骤二:使用opencv的matchTemplate函数(其中输入分别为A,B区域),通过TM_CCORR_NORMED相关操作计算出最大响应值,从而得到偏移量。
步骤三:得到偏移量之后,就能得到左右两张图像的重叠区域。通过左右的重叠区域,需要经过过度化处理,来消除拼接缝隙。过度代码如下所示。
Mat overlay1 = image1(Rect(800 - image_source_width + maxLoc.x, 0, image_source_width - maxLoc.x, image1.rows - 10 + maxLoc.y)); //左边区域
Mat overlay2 = image2(Rect(0, 10 - maxLoc.y, image_source_width - maxLoc.x, image2.rows - 10 + maxLoc.y)); //右边区域
Mat overlay = Mat::zeros(overlay2.rows, overlay2.cols, CV_8UC1);
for (int i = 0; i< overlay2.rows; i++)
{
uchar* dataoverlay1 = overlay1.ptr(i);
uchar* dataoverlay2 = overlay2.ptr(i);
uchar* dataoverlay = overlay.ptr(i);
for (int j = 0; j<overlay2.cols; j++)
{
double weight;
weight = (double)j / overlay2.cols; //随距离改变而改变的叠加系数
dataoverlay[j] = (1 - weight)*dataoverlay1[j] + weight*dataoverlay2[j];
}
}
步骤四:由于拼接全景相机,要求实时的显示,不能全部拼接完才显示,所以需要将重叠区域,移植到左帧,并显示该帧。
拼接图像的前3帧和最后完成的结果如下图所示:
实现代码链接如下: