2014-05-04 127 views
3

我正在做圖像拼接OpenCV(全景),但我有一個問題。Opencv圖像拼接或全景

我不能使用OpenCV拼接類,所以我必須創建它只有特徵點和單應性。

OrbFeatureDetector detector(minHessian); 

std::vector<KeyPoint> keypoints_1, keypoints_2; 

Mat descriptors_1a, descriptors_2a; 
detector.detect(img_1, keypoints_1 , descriptors_1a); 
detector.detect(img_2, keypoints_2 , descriptors_2a); 

//-- Step 2: Calculate descriptors (feature vectors) 
OrbDescriptorExtractor extractor; 

Mat descriptors_1, descriptors_2; 
cout<<"La distancia es " <<endl; 
extractor.compute(img_1, keypoints_1, descriptors_1); 
extractor.compute(img_2, keypoints_2, descriptors_2); 

//-- Step 3: Matching descriptor vectors with a brute force matcher 
BFMatcher matcher(NORM_HAMMING, true); 
std::vector<DMatch> matches; 
matcher.match(descriptors_1, descriptors_2, matches); 

在這裏,我得到的特徵點的比賽,但我需要對其進行過濾:

double max_dist = 0; double min_dist = 100; 

    //-- Quick calculation of max and min distances between keypoints 
    for(int i = 0; i < matches.size(); i++) 
    { 
     double dist = matches[i].distance; 

    //cout<<"La distancia es " << i<<endl; 
    if(dist < min_dist && dist >3) 
     { 

      min_dist = dist; 
     } 
    if(dist > max_dist) max_dist = dist; 
    } 

    //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist) 
    std::vector<DMatch> good_matches; 

    for(int i = 0; i < matches.size(); i++) 
    { 
     //cout<<matches[i].distance<<endl; 
     if(matches[i].distance < 3*min_dist && matches[i].distance > 3) 
    { 
      good_matches.push_back(matches[i]); } 
    } 

現在,我計算出單應

vector<Point2f> p1, p2; 
    for (unsigned int i = 0; i < matches.size(); i++) { 
     p1.push_back(keypoints_1[matches[i].queryIdx].pt); 
     p2.push_back(keypoints_2[matches[i].trainIdx].pt); 
    } 

    // Homografía 
    vector<unsigned char> match_mask; 
    Mat h = findHomography(Mat(p1),Mat(p2), match_mask,CV_RANSAC); 

最後,獲得變換矩陣並應用warpPerspective來獲得這兩個圖像的連接,但我的問題是,在最終圖像中,在照片周圍出現黑色區域​​,並且當我再次循環時,最終圖像將是ile不計。

// Transformar perspectiva para imagen 2 
    vector<Point2f> cuatroPuntos; 
    cuatroPuntos.push_back(Point2f (0,0)); 
    cuatroPuntos.push_back(Point2f (img_1.size().width,0)); 
    cuatroPuntos.push_back(Point2f (0, img_1.size().height)); 
    cuatroPuntos.push_back(Point2f (img_1.size().width, img_1.size().height)); 
    Mat MDestino; 
    perspectiveTransform(Mat(cuatroPuntos), MDestino, h); 

    // Calcular esquinas de imagen 2 
    double min_x, min_y, tam_x, tam_y; 
    float min_x1, min_x2, min_y1, min_y2, max_x1, max_x2, max_y1, max_y2; 
    min_x1 = min(MDestino.at<Point2f>(0).x, MDestino.at<Point2f>(1).x); 
    min_x2 = min(MDestino.at<Point2f>(2).x, MDestino.at<Point2f>(3).x); 
    min_y1 = min(MDestino.at<Point2f>(0).y, MDestino.at<Point2f>(1).y); 
    min_y2 = min(MDestino.at<Point2f>(2).y, MDestino.at<Point2f>(3).y); 
    max_x1 = max(MDestino.at<Point2f>(0).x, MDestino.at<Point2f>(1).x); 
    max_x2 = max(MDestino.at<Point2f>(2).x, MDestino.at<Point2f>(3).x); 
    max_y1 = max(MDestino.at<Point2f>(0).y, MDestino.at<Point2f>(1).y); 
    max_y2 = max(MDestino.at<Point2f>(2).y, MDestino.at<Point2f>(3).y); 
    min_x = min(min_x1, min_x2); 
    min_y = min(min_y1, min_y2); 
    tam_x = max(max_x1, max_x2); 
    tam_y = max(max_y1, max_y2); 

    // Matriz de transformación 
    Mat Htr = Mat::eye(3,3,CV_64F); 
    if (min_x < 0){ 
     tam_x = img_2.size().width - min_x; 
     Htr.at<double>(0,2)= -min_x; 
    } 
    if (min_y < 0){ 
     tam_y = img_2.size().height - min_y; 
     Htr.at<double>(1,2)= -min_y; 
    } 

    // Construir panorama 
    Mat Panorama; 
    Panorama = Mat(Size(tam_x,tam_y), CV_32F); 
    warpPerspective(img_2, Panorama,  Htr, Panorama.size(), INTER_LINEAR, BORDER_CONSTANT, 0); 
    warpPerspective(img_1, Panorama, (Htr*h), Panorama.size(), INTER_LINEAR, BORDER_TRANSPARENT,0); 

任何人都知道我該如何消除這個黑色區域?我做得不好嗎?任何人都知道我可以看到的功能代碼來比較它嗎?

感謝您的時間

編輯:

這就是我的形象:

enter image description here

而且我想消除的黑色部分。

+0

。所以你可以做兩件事來避免黑色區域:1.找到全景的內部矩形,並將所有的黑色區域與一些好的全景圖像部分一起收割掉。 2.在邊界處「拉伸」全景圖像以適應任何矩形,您應該看看「樣條插值」。告訴我你想實現的任何方法,我會盡力幫助你。也許張貼樣品圖像,並標記你想要舉行/裁剪的地區;) – Micka

回答

1

正如Micka建議的那樣,當您拼接時,全景通常是波浪形的,因爲單應性或其他投影方法不會將矩形映射到另一個矩形。你可以通過使用一些「矯直」來補償這種效應,參考這篇文章:

M.Brown和D.G.Lowe。使用不變特徵的自動全景圖像拼接。 IJCV,74(1):59-73,2007

至於剪裁黑色部分,我寫了這個類,你可以使用。該類假定圖像爲BGR,黑色像素的值爲Vec3b(0,0,0)。源代碼可以在這裏訪問:

https://github.com/chmos/crop-images.git

最佳,

當你縫2個圖像這是非常不可能的全景將在真正的矩形最終
+0

我自己做一個拼接器,但不只是一個pano。如果有意義的話,它可以在x軸和y軸上進行縫合。我想知道你是否可以解釋你的代碼,特別是Mat HTR :: eye的部分。我已經想通了,我需要透視將兩張圖像轉換爲空白的畫布/圖像,但您所擁有的部分是我所缺少的難題。感謝您的幫助提前。 –