影像拼接简介
影像拼接(image stitching)是指将两张或更多的有重叠部分的影像,拼接成一张全景图或是高分辨率影像的技术。影像拼接有两大步骤:影像对准(image alignment)和影像混合(blending/compositing)
影像对准
影像对准是指找出两张影像之间的变换关系,如平移、旋转、缩放,经过变换之后使两张影像中相同的部分可以重叠。影像之间的变换关系可以用一个矩阵来表示,所要求得的矩阵的未知数数量越多,代表两影像之间的关系越复杂、越难对准。举例而言,平移矩阵有两个未知数,仿射变换矩阵有六个未知数,而一般化的投影矩阵则有八个未知数。为简化问题,在拍摄影像时会尽量避免同时平移、旋转或缩放,以简化对准的难度。通常会先取得影像的特征点,再透过影像配准(image registration)完成对准。
特征点检测
特征点检测是指借由影像的亮度、颜色、梯度等资讯,寻找影像中的特征点的方法。在影像对准中,可以用特征点检测来取得两张影像的特征点,再借由配对这些特征点来完成对准。常见的特征点检测的方法有:哈里斯角检测(Harris Corner Detection)、尺度不变特征转换(SIFT)等,特征点通常会是影像中物体的角落,或是颜色变化大的地方。然而,因为要被对准两影像重叠部分有限,共有的特征点并不多,大部分特征点都是离群值(outlier),因此需要影像配准的技术来完成特征点的对应。
影像配准
影像配准是指将影像经过变换后,使得两影像的相似程度最大的技术,计算相似程度的方法因算法而异,举例来说,两影像的方均根差即可当作相似程度的指标,方均根差越小表示影像越相似。在影像对准中,影像配准能够借由最大化影像重叠部分的相似程度,来完成影像之间特征点的对应。随机抽样一致算法(RANSAC)是影像配准最常见的算法之一,透过递回和取样,来找到最适当的变换,随机抽样一致算法并不是确定性算法,但其优点是可以在有许多离群值当中,为内群值找到一个合理的变换,适合用在离群值多的影像配准问题上。
影像混合
因为视差、镜头失真、曝光差异等因素,两张已经对准的影像仍可能有明显的边界而不像一张完整的合成影像,影像混合就是指让对准后的影像能平顺地拼接的技术[1]。常见的方法有阿尔法混合(alpha blending)、梯度域拼接(gradient-domain stitching)[2]等。
与传统遥感影像镶嵌的区别
影像拼接要比遥感影像镶嵌更为复杂,遥感影像镶嵌是在完成地理配准的基础上的拼接,两幅影像同名点地理坐标误差很小通常不需要进行影像对准。
代码实现
opencv stitching类实现拼接
#include <iostream>
#include <opencv2/highgui.hpp>
#include<opencv2/stitching.hpp>
using namespace std;
using namespace cv;
bool try_use_gpu = false;
vector<Mat> imgs;
string result_name = "result1.tif";
int main(int argc, char * argv[])
{
Mat img1 = imread("D:/gdalData/match_mosaic/50051016_0_rec.tif");
Mat img2 = imread("D:/gdalData/match_mosaic/50051017_0_rec.tif");
if (img1.empty() || img2.empty())
{
cout << "Can't read image" << endl;
return -1;
}
imgs.push_back(img1);
imgs.push_back(img2);
Stitcher stitcher = Stitcher::createDefault(try_use_gpu);
// 使用stitch函数进行拼接
Mat pano;
Stitcher::Status status = stitcher.stitch(imgs, pano);
imwrite(result_name, pano);
//Mat pano2 = pano.clone();
// 显示源图像,和结果图像
imshow("全景图像", pano);
if (waitKey() == 27)
return 0;
}