影像拼接簡(jiǎn)介
影像拼接(image stitching)是指將兩張或更多的有重疊部分的影像粘优,拼接成一張全景圖或是高分辨率影像的技術(shù)链峭。影像拼接有兩大步驟:影像對(duì)準(zhǔn)(image alignment)和影像混合(blending/compositing)
影像對(duì)準(zhǔn)
影像對(duì)準(zhǔn)是指找出兩張影像之間的變換關(guān)系框咙,如平移、旋轉(zhuǎn)传惠、縮放谦去,經(jīng)過變換之后使兩張影像中相同的部分可以重疊。影像之間的變換關(guān)系可以用一個(gè)矩陣來表示外傅,所要求得的矩陣的未知數(shù)數(shù)量越多纪吮,代表兩影像之間的關(guān)系越復(fù)雜、越難對(duì)準(zhǔn)萎胰。舉例而言碾盟,平移矩陣有兩個(gè)未知數(shù),仿射變換矩陣有六個(gè)未知數(shù)技竟,而一般化的投影矩陣則有八個(gè)未知數(shù)冰肴。為簡(jiǎn)化問題,在拍攝影像時(shí)會(huì)盡量避免同時(shí)平移榔组、旋轉(zhuǎn)或縮放熙尉,以簡(jiǎn)化對(duì)準(zhǔn)的難度。通常會(huì)先取得影像的特征點(diǎn)搓扯,再透過影像配準(zhǔn)(image registration)完成對(duì)準(zhǔn)检痰。
特征點(diǎn)檢測(cè)
特征點(diǎn)檢測(cè)是指借由影像的亮度、顏色锨推、梯度等資訊铅歼,尋找影像中的特征點(diǎn)的方法公壤。在影像對(duì)準(zhǔn)中,可以用特征點(diǎn)檢測(cè)來取得兩張影像的特征點(diǎn)谭贪,再借由配對(duì)這些特征點(diǎn)來完成對(duì)準(zhǔn)境钟。常見的特征點(diǎn)檢測(cè)的方法有:哈里斯角檢測(cè)(Harris Corner Detection)锦担、尺度不變特征轉(zhuǎn)換(SIFT)等俭识,特征點(diǎn)通常會(huì)是影像中物體的角落,或是顏色變化大的地方洞渔。然而套媚,因?yàn)橐粚?duì)準(zhǔn)兩影像重疊部分有限,共有的特征點(diǎn)并不多磁椒,大部分特征點(diǎn)都是離群值(outlier)堤瘤,因此需要影像配準(zhǔn)的技術(shù)來完成特征點(diǎn)的對(duì)應(yīng)。
影像配準(zhǔn)
影像配準(zhǔn)是指將影像經(jīng)過變換后浆熔,使得兩影像的相似程度最大的技術(shù)本辐,計(jì)算相似程度的方法因算法而異,舉例來說医增,兩影像的方均根差即可當(dāng)作相似程度的指標(biāo)慎皱,方均根差越小表示影像越相似。在影像對(duì)準(zhǔn)中叶骨,影像配準(zhǔn)能夠借由最大化影像重疊部分的相似程度茫多,來完成影像之間特征點(diǎn)的對(duì)應(yīng)。隨機(jī)抽樣一致算法(RANSAC)是影像配準(zhǔn)最常見的算法之一忽刽,透過遞回和取樣天揖,來找到最適當(dāng)?shù)淖儞Q,隨機(jī)抽樣一致算法并不是確定性算法跪帝,但其優(yōu)點(diǎn)是可以在有許多離群值當(dāng)中今膊,為內(nèi)群值找到一個(gè)合理的變換,適合用在離群值多的影像配準(zhǔn)問題上伞剑。
影像混合
因?yàn)橐暡畎呋!㈢R頭失真、曝光差異等因素纸泄,兩張已經(jīng)對(duì)準(zhǔn)的影像仍可能有明顯的邊界而不像一張完整的合成影像赖钞,影像混合就是指讓對(duì)準(zhǔn)后的影像能平順地拼接的技術(shù)[1]。常見的方法有阿爾法混合(alpha blending)聘裁、梯度域拼接(gradient-domain stitching)[2]等雪营。
與傳統(tǒng)遙感影像鑲嵌的區(qū)別
影像拼接要比遙感影像鑲嵌更為復(fù)雜,遙感影像鑲嵌是在完成地理配準(zhǔn)的基礎(chǔ)上的拼接衡便,兩幅影像同名點(diǎn)地理坐標(biāo)誤差很小通常不需要進(jìn)行影像對(duì)準(zhǔn)献起。
代碼實(shí)現(xiàn)
opencv stitching類實(shí)現(xiàn)拼接
#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函數(shù)進(jìn)行拼接
Mat pano;
Stitcher::Status status = stitcher.stitch(imgs, pano);
imwrite(result_name, pano);
//Mat pano2 = pano.clone();
// 顯示源圖像洋访,和結(jié)果圖像
imshow("全景圖像", pano);
if (waitKey() == 27)
return 0;
}