基于opencv3.1的特征检测、特征点匹配、图像拼接(四)
在上一节的过程中,我们已经掌握了opencv自带的两个接口函数findHomography和perspectiveTransform,并修改了opencv官方手册中的一些存在的版本兼容问题。然后,根据得到的单应性矩阵H,我们得到了图像间的投影变换关系。我们可以将其中一张图像每个像素点进行投影变换,最后将变换后的图片与另一张图片进行图片叠加即可得到初步的拼接结果。
首先我们默认将右侧的图片进行投影变换覆盖到左侧图像上(反之同理,但是需要将代码细节改正一下,比如投影输出图像的尺寸等),所用到的接口为warpPerspective:
void warpPerspective(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())
第一个参数src是输入待处理的图像,第二个参数dst是我们投影变换后的输出图像;第三个参数是单应性矩阵H,第四个参数是输出图像的大小,剩下的参数为常量。此处我们需要注意第四个参数:因为做投影变换的图像是右侧的图,其图像的宽度width(cols)应该是右侧图像投影到左侧图像之后,最右边的右上角和右下角两个点的x值的最大值。高度我们取为左侧图片的高度。代码表示如下:
warpPerspective(img1, imageTransform1, H, Size(MAX(corners.right_top.x, corners.right_bottom.x), img2.rows));
因此我们在执行这段代码之前,必须先解算出右图投影在左图时的四个边角的坐标,即size参数值,代码如下(摘选自opencv手册中的源码):
//直接进行图像投影变换
std::vector<Point2f> obj_corners(4);//定义右图的四个角
obj_corners[0] = cvPoint(0, 0);
obj_corners[1] = cvPoint(img1.cols, 0);
obj_corners[2] = cvPoint(img1.cols, img1.rows);
obj_corners[3] = cvPoint(0, img1.rows);
std::vector<Point2f> scene_corners(4);//定义左图的四个角
perspectiveTransform(obj_corners, scene_corners, H);//将右图四角投影至左图
cout << "left_top:" << scene_corners[0].x <<" "<<scene_corners[0].y<< endl;
cout << "right_top:" << scene_corners[1].x << " " << scene_corners[1].y << endl;
cout << "right_bottom:" << scene_corners[2].x << " " << scene_corners[2].y << endl;
cout << "left_bottom:" << scene_corners[3].x << " " << scene_corners[3].y << endl;
Mat imageTransform1, imageTransform2;
warpPerspective(img1, imageTransform1, H, Size(MAX(scene_corners[1].x, scene_corners[2].x), img2.rows));
imshow("投影变换右图", imageTransform1);
imwrite("trans1.jpg", imageTransform1);
运行效果如下:
接下来,将左图覆盖在dst上面,这里我们要用到函数:copyTo;这个函数浪费了我整整一天的时间…因为我之前的代码风格都是在读取图片的时候,像这样直接读成灰度图:
Mat img_object = imread("box.png", IMREAD_GRAYSCALE);
如果原图是灰度图,那么copyTo不会报错,但是如果读取过程中使用灰度图像的读取方式就会报错,内存泄漏,本人能力有限,没有具体分析产生这样的问题的原因,只是把imread后面代表灰度的参数删掉了保证了程序的稳定运行;关于图像拷贝与覆盖这部分的代码为:
int dst_width = imageTransform1.cols; //为拼接图的长度
int dst_height = img2.rows