如何将 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 内核编码风格;这就是我避免使用 typedef
s、namespace
s 并在所有事情之前写下 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
首先,这是我第一次使用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 内核编码风格;这就是我避免使用 typedef
s、namespace
s 并在所有事情之前写下 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