2014-05-04 97 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的部分。我已经想通了,我需要透视将两张图像转换为空白的画布/图像,但您所拥有的部分是我所缺少的难题。感谢您的帮助提前。 –