OpenCV - FAST+BRIEF:如何使用 DrawMatchesFlags::DRAW_RICH_KEYPOINTS 绘制关键点?
OpenCV - FAST+BRIEF: How to draw keypoints with DrawMatchesFlags::DRAW_RICH_KEYPOINTS?
我必须使用 FAST+BRIEF 实现特征检测器(如果我理解正确的话,这是 ORB 的手动实现)。
所以,这是我目前的代码:
printf("Calculating FAST+BRIEF features...\n");
Ptr<FastFeatureDetector> FASTdetector = FastFeatureDetector::create();
Ptr<BriefDescriptorExtractor> BRIEFdescriptor = BriefDescriptorExtractor::create();
std::vector<cv::KeyPoint> FASTkeypoints_1, FASTkeypoints_2, FASTkeypoints_3;
Mat BRIEFdescriptors_1, BRIEFdescriptors_2, BRIEFdescriptors_3;
FASTdetector->detect(left08, FASTkeypoints_1);
FASTdetector->detect(right08, FASTkeypoints_2);
FASTdetector->detect(left10, FASTkeypoints_3);
BRIEFdescriptor->compute(left08, FASTkeypoints_1, BRIEFdescriptors_1);
BRIEFdescriptor->compute(right08, FASTkeypoints_2, BRIEFdescriptors_2);
BRIEFdescriptor->compute(left10, FASTkeypoints_3, BRIEFdescriptors_3);
Mat FAST_left08, FAST_right08, FAST_left10;
drawKeypoints(left08, FASTkeypoints_1, FAST_left08, FASTBRIEFfeatcol_YELLOW, DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imwrite("../Results/FASTBRIEF_left08.png", FAST_left08);
drawKeypoints(right08, FASTkeypoints_2, FAST_right08, FASTBRIEFfeatcol_YELLOW, DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imwrite("../Results/FASTBRIEF_right08.png", FAST_right08);
drawKeypoints(left10, FASTkeypoints_3, FAST_left10, FASTBRIEFfeatcol_YELLOW, DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imwrite("../Results/FASTBRIEF_left10.png", FAST_left10);
printf("FAST+BRIEF done. \n");
到目前为止,代码运行良好,但是我没有得到丰富的关键点,而是得到了标准的关键点。如果我理解正确的话,这是因为我需要先以某种方式将描述符信息获取到关键点,对吗?
我之前用 SIFT、SURF 和 ORB 做过同样的实现,但是我直接使用 computeanddetect
函数,它给了我关键点,我可以在其中用 DrawMatchesFlags::DRAW_RICH_KEYPOINTS
标志绘制.
I have to implement a feature detector using FAST+BRIEF (which is the manual implementation of ORB if I understand correctly).
是的,没错。
If I understand correctly, this is because I need to somehow get the descriptor information to the keypoints first, right?
不是,关键点是通过不同的方法检测的。您可以使用 SIFT、FAST、HarrisDetector、SURF 等。首先只检测 个关键点。然后有不同的方法来描述检测到的关键点(例如 SIFT 的 128 位浮点矢量描述符)并在之后匹配它们。
OpenCV中的一个关键点可以用角度、大小、八度等不同的属性来描述https://docs.opencv.org/3.4.2/d2/d29/classcv_1_1KeyPoint.html
对于 SIFT,每个 KeyPoint 属性都填充有一个数字,稍后可以在 DRAW_RICH_KEYPOINTS
标志中绘制。对于 FAST,只分配属性的标准值,以便可以使用提到的标志绘制它们的关键点,但大小、倍频程和角度不变。因此,每个绘制的关键点看起来都很相似。
这里有一个小代码示例作为证明(我只使用 ->detect
函数):
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>
int main(int argc, char** argv)
{
// Load image
cv::Mat img = cv::imread("MT189.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (!img.data) {
std::cout << "Error reading image" << std::endl;
return EXIT_FAILURE;
}
cv::Mat output;
// Detect FAST keypoints
std::vector<cv::KeyPoint> keypoints_fast, keypoints_sift;
cv::Ptr<cv::FastFeatureDetector> fast = cv::FastFeatureDetector::create();
fast->detect(img, keypoints_fast);
for (size_t i = 0; i < 100; ++i) {
std::cout << "FAST Keypoint #:" << i;
std::cout << " Size " << keypoints_fast[i].size << " Angle " << keypoints_fast[i].angle << " Response " << keypoints_fast[i].response << " Octave " << keypoints_fast[i].octave << std::endl;
}
// Detect SIFT keypoints
cv::Ptr<cv::xfeatures2d::SiftFeatureDetector> sift = cv::xfeatures2d::SiftFeatureDetector::create();
sift->detect(img, keypoints_sift);
for (size_t i = 0; i < 100; ++i) {
std::cout << "SIFT Keypoint #:" << i;
std::cout << " Size " << keypoints_sift[i].size << " Angle " << keypoints_sift[i].angle << " Response " << keypoints_sift[i].response << " Octave " << keypoints_sift[i].octave << std::endl;
}
// Draw SIFT keypoints
cv::drawKeypoints(img, keypoints_sift, output, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
cv::imshow("Output", output);
cv::waitKey(0);
}
我必须使用 FAST+BRIEF 实现特征检测器(如果我理解正确的话,这是 ORB 的手动实现)。
所以,这是我目前的代码:
printf("Calculating FAST+BRIEF features...\n");
Ptr<FastFeatureDetector> FASTdetector = FastFeatureDetector::create();
Ptr<BriefDescriptorExtractor> BRIEFdescriptor = BriefDescriptorExtractor::create();
std::vector<cv::KeyPoint> FASTkeypoints_1, FASTkeypoints_2, FASTkeypoints_3;
Mat BRIEFdescriptors_1, BRIEFdescriptors_2, BRIEFdescriptors_3;
FASTdetector->detect(left08, FASTkeypoints_1);
FASTdetector->detect(right08, FASTkeypoints_2);
FASTdetector->detect(left10, FASTkeypoints_3);
BRIEFdescriptor->compute(left08, FASTkeypoints_1, BRIEFdescriptors_1);
BRIEFdescriptor->compute(right08, FASTkeypoints_2, BRIEFdescriptors_2);
BRIEFdescriptor->compute(left10, FASTkeypoints_3, BRIEFdescriptors_3);
Mat FAST_left08, FAST_right08, FAST_left10;
drawKeypoints(left08, FASTkeypoints_1, FAST_left08, FASTBRIEFfeatcol_YELLOW, DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imwrite("../Results/FASTBRIEF_left08.png", FAST_left08);
drawKeypoints(right08, FASTkeypoints_2, FAST_right08, FASTBRIEFfeatcol_YELLOW, DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imwrite("../Results/FASTBRIEF_right08.png", FAST_right08);
drawKeypoints(left10, FASTkeypoints_3, FAST_left10, FASTBRIEFfeatcol_YELLOW, DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
imwrite("../Results/FASTBRIEF_left10.png", FAST_left10);
printf("FAST+BRIEF done. \n");
到目前为止,代码运行良好,但是我没有得到丰富的关键点,而是得到了标准的关键点。如果我理解正确的话,这是因为我需要先以某种方式将描述符信息获取到关键点,对吗?
我之前用 SIFT、SURF 和 ORB 做过同样的实现,但是我直接使用 computeanddetect
函数,它给了我关键点,我可以在其中用 DrawMatchesFlags::DRAW_RICH_KEYPOINTS
标志绘制.
I have to implement a feature detector using FAST+BRIEF (which is the manual implementation of ORB if I understand correctly).
是的,没错。
If I understand correctly, this is because I need to somehow get the descriptor information to the keypoints first, right?
不是,关键点是通过不同的方法检测的。您可以使用 SIFT、FAST、HarrisDetector、SURF 等。首先只检测 个关键点。然后有不同的方法来描述检测到的关键点(例如 SIFT 的 128 位浮点矢量描述符)并在之后匹配它们。
OpenCV中的一个关键点可以用角度、大小、八度等不同的属性来描述https://docs.opencv.org/3.4.2/d2/d29/classcv_1_1KeyPoint.html
对于 SIFT,每个 KeyPoint 属性都填充有一个数字,稍后可以在 DRAW_RICH_KEYPOINTS
标志中绘制。对于 FAST,只分配属性的标准值,以便可以使用提到的标志绘制它们的关键点,但大小、倍频程和角度不变。因此,每个绘制的关键点看起来都很相似。
这里有一个小代码示例作为证明(我只使用 ->detect
函数):
#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/xfeatures2d/nonfree.hpp>
int main(int argc, char** argv)
{
// Load image
cv::Mat img = cv::imread("MT189.jpg", CV_LOAD_IMAGE_GRAYSCALE);
if (!img.data) {
std::cout << "Error reading image" << std::endl;
return EXIT_FAILURE;
}
cv::Mat output;
// Detect FAST keypoints
std::vector<cv::KeyPoint> keypoints_fast, keypoints_sift;
cv::Ptr<cv::FastFeatureDetector> fast = cv::FastFeatureDetector::create();
fast->detect(img, keypoints_fast);
for (size_t i = 0; i < 100; ++i) {
std::cout << "FAST Keypoint #:" << i;
std::cout << " Size " << keypoints_fast[i].size << " Angle " << keypoints_fast[i].angle << " Response " << keypoints_fast[i].response << " Octave " << keypoints_fast[i].octave << std::endl;
}
// Detect SIFT keypoints
cv::Ptr<cv::xfeatures2d::SiftFeatureDetector> sift = cv::xfeatures2d::SiftFeatureDetector::create();
sift->detect(img, keypoints_sift);
for (size_t i = 0; i < 100; ++i) {
std::cout << "SIFT Keypoint #:" << i;
std::cout << " Size " << keypoints_sift[i].size << " Angle " << keypoints_sift[i].angle << " Response " << keypoints_sift[i].response << " Octave " << keypoints_sift[i].octave << std::endl;
}
// Draw SIFT keypoints
cv::drawKeypoints(img, keypoints_sift, output, cv::Scalar::all(-1), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
cv::imshow("Output", output);
cv::waitKey(0);
}