如何将 OpenCV 中的 2 张图像与 ORB 对齐? (编译失败)

How to align 2 images in OpenCV with ORB? (fail to compile)

首先,这是我第一次使用C++。我正在使用 C++,因为 OpenCV 在 C 中非常有限。

OpenCV 文档并不是我见过的最详尽的文档。

我已经尝试重写这个 ORB example 以便在我的项目中使用。

密码是:

img_orb.cpp:

/******************************************************************************
 ******* headers **************************************************************
 ******************************************************************************/
/* Standard (C++) ------------------------------------------------------------*/
        /* std::vector */
    #include <vector>

/* Packages ------------------------------------------------------------------*/
        /* opencv */
    #include <opencv2/opencv.hpp>
    #include <opencv2/features2d/features2d.hpp>

/* Project -------------------------------------------------------------------*/
    #include "img_orb.hpp"


/******************************************************************************
 ******* macros ***************************************************************
 ******************************************************************************/
    # define    MAX_FEATURES    (500)
    # define    GOOD_MATCH_P    (0.15)


/******************************************************************************
 ******* main *****************************************************************
 ******************************************************************************/
void    img_orb_align   (struct _IplImage  *pattern,
                struct _IplImage  *imgptr)
{
    /* Transform (struct _IplImage *) to (class cv::Mat) */
    /* Make a copy so that they aren't modified */
    class cv::Mat   img_0;
    class cv::Mat   img_1;
    img_0   = cv::cvarrToMat(pattern, true);
    img_1   = cv::cvarrToMat(imgptr, true);

    /* Variables to store keypoints & descriptors */
    std::vector <class cv::KeyPoint>    keypoints_0;
    std::vector <class cv::KeyPoint>    keypoints_1;
    class cv::Mat               descriptors_0;
    class cv::Mat               descriptors_1;

    /* Detect ORB features & compute descriptors */
    class cv::Ptr <class cv::Feature2D> orb;
    orb = cv::ORB::create(MAX_FEATURES);
    orb->detectAndCompute(img_0, cv::Mat(), keypoints_0, descriptors_0);
    orb->detectAndCompute(img_1, cv::Mat(), keypoints_1, descriptors_1);

    /* Match structures */
    std::vector <struct cv::DMatch>     matches;
    cv::Ptr <class cv::DescriptorMatcher>   matcher;
    matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
    matcher->match(descriptors_1, descriptors_0, matches, cv::Mat());

    /* Sort matches by score */
    std::sort(matches.begin(), matches.end());

    /* Remove not so good matches */
    int good_matches;
    good_matches    = GOOD_MATCH_P * matches.size();
    matches.erase(matches.begin() + good_matches, matches.end());

    /* Draw top matches */
    class cv::Mat   img_matches;
    cv::drawMatches(img_1, keypoints_1, img_0, keypoints_0, matches,
                                img_matches);
    cv::imwrite("matches.jpg", img_matches);

    /* Extract location of good matches */
    std::vector <class cv::Point_ <float>>  points_0;
    std::vector <class cv::Point_ <float>>  points_1;
    int i;  
    for (i = 0; i < matches.size(); i++) {
        points_1.push_back(keypoints_1[matches[i].queryIdx].pt);
        points_0.push_back(keypoints_0[matches[i].trainIdx].pt);
    }

    /* Find homography */
    class cv::Mat   img_hg;
    img_hg  = cv::findHomography(points_1, points_0, CV_RANSAC);

    /* Use homography to warp image */
    class cv::Mat   img_align;
    cv::warpPerspective(img_1, img_align, img_hg, img_0.size());

    /* Write img_align into imgptr */
    *imgptr = img_align;
}


/******************************************************************************
 ******* end of file **********************************************************
 ******************************************************************************/

注意:当我写 C 时,我总是尽量遵循 Linux 内核编码风格;这就是我避免使用 typedefs、namespaces 并在所有事情之前写下 class 和所有这些东西的原因;我喜欢让一切都非常明确。

第一件事是我必须删除 #include "opencv2/xfeatures2d.hpp",因为 header 在我的系统 (Debian Stretch) 上不存在。但是,我读到 header here,它似乎没有包含我的问题的解决方案。

当我编译该文件时,出现以下错误:

/.../img_orb.cpp: In function ‘void img_orb_align(_IplImage*, _IplImage*)’:
/.../img_orb.cpp:78:36: error: no matching function for call to ‘cv::ORB::create(int)’
  orb = cv::ORB::create(MAX_FEATURES);
                                    ^
In file included from /usr/include/opencv2/opencv.hpp:53:0,
                 from /.../img_orb.cpp:19:
/usr/include/opencv2/features2d/features2d.hpp:269:35: note: candidate: static cv::Ptr<cv::Feature2D> cv::Feature2D::create(const string&)
     CV_WRAP static Ptr<Feature2D> create( const string& name );
                                   ^~~~~~
/usr/include/opencv2/features2d/features2d.hpp:269:35: note:   no known conversion for argument 1 from ‘int’ to ‘const string& {aka const std::__cxx11::basic_string<char>&}’
/.../img_orb.cpp:79:7: error: ‘class cv::Feature2D’ has no member named ‘detectAndCompute’; did you mean ‘detectImpl’?
  orb->detectAndCompute(img_0, cv::Mat(), keypoints_0, descriptors_0);
       ^~~~~~~~~~~~~~~~
/.../img_orb.cpp:80:7: error: ‘class cv::Feature2D’ has no member named ‘detectAndCompute’; did you mean ‘detectImpl’?
  orb->detectAndCompute(img_1, cv::Mat(), keypoints_1, descriptors_1);
       ^~~~~~~~~~~~~~~~
Makefile:101: recipe for target 'img_orb.s' failed

我举的例子是不是简单坏了?它失败是因为我缺少一个 header 吗?它失败是因为我不了解一些 C++ 的东西吗?否则?

编辑:

像这样安装 OpenCV:apt-get install libopencv-dev

debian stretch 中的版本是:2.4.9.1+dfsg1-2

更改代码的以下部分:

void    img_orb_align   (struct _IplImage  *pattern,
                struct _IplImage  **imgptr2)

...

*imgptr2

代替imgptr

...

    /* Detect ORB features & compute descriptors */
    /* This works in openCV 2.4, but does not work in openCV 3.x */
    class cv::ORB   orb;
    orb(img_0, cv::Mat(), keypoints_0, descriptors_0);
    orb(img_1, cv::Mat(), keypoints_1, descriptors_1);
#if 0
    /* This did not work in openCV 2.4;  It does work in openCV 3.x */
    class cv::Ptr <class cv::Feature2D> orb;
    orb = cv::ORB::create(MAX_FEATURES);
    orb->detectAndCompute(img_0, cv::Mat(), keypoints_0, descriptors_0);
    orb->detectAndCompute(img_1, cv::Mat(), keypoints_1, descriptors_1);
#endif

...

    /* Write img_align into imgptr (need a tmp img;  don't know why) */
    struct _IplImage    imgtmp;
    int         cols;
    int         rows;
    int         depth;
    int         chan;
    cols        = img_align.cols;
    rows        = img_align.rows;
    depth       = (*imgptr2)->depth;
    chan        = (*imgptr2)->nChannels;
    cvReleaseImage(imgptr2);
    *imgptr2    = cvCreateImage(cvSize(cols, rows), depth, chan);
    imgtmp      = img_align;
    cvCopy(&imgtmp, *imgptr2);
    img_align.release();
#if 0
    /* This did not work */
    *imgptr = img_align;
#endif