工程配置
采用CLion+Ubuntu20.04进行开发,新建工程Study 。
工程结构
结构如下:
.
├── CMakeLists.txt
├── include
│ └── main.h
└── src
├── CMakeLists.txt
└── main.cpp
子目录include 用于存放头文件;子目录src 用于存放源码
CMake配置
根目录下CMakeLists.txt 文件内容如下:
cmake_minimum_required(VERSION 3.21)
project(Study)
set(CMAKE_CXX_STANDARD 14)
find_package(OpenCV REQUIRED)
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(include)
add_subdirectory(src)
src 目录下CMakeLists.txt 文件内容如下:
add_executable(Study main.cpp)
target_link_libraries(Study ${OpenCV_LIBS})
头文件配置
include 目录中头文件main.h 内容如下:
#ifndef STUDY_MAIN_H
#define STUDY_MAIN_H
#include <iostream>
#include <cmath>
#include <chrono>
#include <opencv2/opencv.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <opencv2/imgcodecs/legacy/constants_c.h>
using namespace std;
using namespace cv;
#endif
源文件
src 下源文件main.cpp 初始内容如下:
#include "main.h"
int main()
{
return 0;
}
工程主代码
#include "main.h"
int main(){
Mat img_1 = imread("/home/jasonli/workspace/slambook2/ch7/1.png");
Mat img_2 = imread("/home/jasonli/workspace/slambook2/ch7/2.png");
assert(img_1.data != nullptr && img_2.data != nullptr);
std::vector<KeyPoint> keyPoints_1, keyPoints_2;
Mat descriptors_1, descriptors_2;
Ptr<FeatureDetector> detector = ORB::create();
Ptr<DescriptorExtractor> descriptor = ORB::create();
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");
chrono::steady_clock::time_point t1 = chrono::steady_clock::now();
detector->detect(img_1, keyPoints_1);
detector->detect(img_2, keyPoints_2);
descriptor->compute(img_1, keyPoints_1, descriptors_1);
descriptor->compute(img_2, keyPoints_2, descriptors_2);
chrono::steady_clock::time_point t2 = chrono::steady_clock::now();
chrono::duration<double> time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
cout << "extract ORB cost = " << time_used.count() << " seconds. " << endl;
Mat outImg1;
drawKeypoints(img_1, keyPoints_1, outImg1);
imshow("ORB Features", outImg1);
imwrite("/home/jasonli/pic/ORB_Features.png", outImg1);
vector<DMatch> matches;
t1 = chrono::steady_clock::now();
matcher->match(descriptors_1, descriptors_2, matches);
t2 = chrono::steady_clock::now();
time_used = chrono::duration_cast<chrono::duration<double>>(t2 - t1);
cout << "match ORB cost = " << time_used.count() << " seconds. " << endl;
auto min_max = minmax_element(matches.begin(), matches.end(),
[](const DMatch &m1, const DMatch &m2){return m1.distance < m2.distance; });
double min_dist = min_max.first->distance;
double max_dist = min_max.second->distance;
cout << "Max dist:\t" << max_dist << "\nMin dist:\t" << min_dist << endl;
vector<DMatch> good_matches;
for(int i=0; i < descriptors_1.rows; i++){
if(matches[i].distance <= max(2 * min_dist , 30.0)){
good_matches.push_back(matches[i]);
}
}
Mat img_match;
drawMatches(img_1, keyPoints_1, img_2, keyPoints_2, matches, img_match);
imshow("all matches", img_match);
imwrite("/home/jasonli/pic/all_matches.png", img_match);
Mat img_goodMatch;
drawMatches(img_1, keyPoints_1, img_2, keyPoints_2, good_matches, img_goodMatch);
imshow("good matches", img_goodMatch);
imwrite("/home/jasonli/pic/good_matches.png", img_goodMatch);
waitKey(0);
return 0;
}
输出
内容如下:
extract ORB cost = 0.053812 seconds.
match ORB cost = 0.000748446 seconds.
Max dist: 94
Min dist: 4
特征点图像如下:
未筛选前的匹配如下:
筛选后的匹配如下:
|