实时性特征检测
可以分为两个部分:图像特征提取与匹配
ORB(Oriented FAST and Rotated BRIEF)该特征检测算法是在著名的FAST特征检测和BRIEF特征描述子的基础上提出来的,其运行时间远远优于SIFT和SURF,可应用于实时性特征检测。
遇到过这样一个问题,在双目视觉中,使用矫正的两张图片,计算视差时,需要找到匹配点。
自己写了一个基于灰度值的线特征匹配算法,但是效果会受到图像效果的影响,且二值化的阈值是不固定的。
于是就在网上查资料,发现ORB特征匹配算法,速度很快,实时性好,准确度高,非常有帮助。
话不多说:附上我的测试代码
自己配置一下opencv,我这里测试时用的opencv4.1,如果需要,可以联系我。
两张相似的照片,导入路径,即可使用。
#include<opencv2/opencv.hpp>
#include<iostream>
#include<math.h>
using namespace cv;
using namespace std;
Mat img1, img2;
void ORB_demo(int, void*);
int main(int argc, char** argv)
{
img1 = imread("D:/test/box.png");//替换你自己的路径
img2 = imread("D:/test/box_in_scene.png");
if (!img1.data|| !img2.data)
{
cout << "图片未找到!" << endl;
return -1;
}
namedWindow("ORB_demo",CV_WINDOW_AUTOSIZE);
ORB_demo(0,0);
imshow("input image of box",img1);
imshow("input image of box_in_scene", img2);
waitKey(0);
return 0;
}
/*---------------检测与匹配--------------*/
void ORB_demo(int, void *)
{
int Hession = 400;
double t1 = getTickCount();
//特征点提取
Ptr<ORB> detector = ORB::create(400);
vector<KeyPoint> keypoints_obj;
vector<KeyPoint> keypoints_scene;
//定义描述子
Mat descriptor_obj, descriptor_scene;
//检测并计算成描述子
detector->detectAndCompute(img1, Mat(), keypoints_obj, descriptor_obj);
detector->detectAndCompute(img2, Mat(), keypoints_scene, descriptor_scene);
double t2 = getTickCount();
double t = (t2 - t1) * 1000 / getTickFrequency();
//特征匹配
FlannBasedMatcher fbmatcher(new flann::LshIndexParams(20, 10, 2));
vector<DMatch> matches;
//将找到的描述子进行匹配并存入matches中
fbmatcher.match(descriptor_obj, descriptor_scene, matches);
double minDist = 1000;
double maxDist = 0;
//找出最优描述子
vector<DMatch> goodmatches;
for (int i = 0; i < descriptor_obj.rows; i++)
{
double dist = matches[i].distance;
if (dist < minDist)
{
minDist=dist ;
}
if (dist > maxDist)
{
maxDist=dist;
}
}
for (int i = 0; i < descriptor_obj.rows; i++)
{
double dist = matches[i].distance;
if (dist < max(2 * minDist, 0.02))
{
goodmatches.push_back(matches[i]);
}
}
Mat orbImg;
drawMatches(img1, keypoints_obj, img2, keypoints_scene, goodmatches, orbImg,
Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
//----------目标物体用矩形标识出来------------
vector<Point2f> obj;
vector<Point2f>scene;
for (size_t i = 0; i < goodmatches.size(); i++)
{
obj.push_back(keypoints_obj[goodmatches[i].queryIdx].pt);
scene.push_back(keypoints_scene[goodmatches[i].trainIdx].pt);
}
vector<Point2f> obj_corner(4);
vector<Point2f> scene_corner(4);
//生成透视矩阵
Mat H = findHomography(obj, scene, RANSAC);
obj_corner[0] = Point(0, 0);
obj_corner[1] = Point(img1.cols, 0);
obj_corner[2] = Point(img1.cols, img1.rows);
obj_corner[3] = Point(0, img1.rows);
//透视变换
perspectiveTransform(obj_corner, scene_corner, H);
Mat resultImg=orbImg.clone();
for (int i = 0; i < 4; i++)
{
line(resultImg, scene_corner[i]+ Point2f(img1.cols, 0), scene_corner[(i + 1) % 4]+ Point2f(img1.cols, 0), Scalar(0, 0, 255), 2, 8, 0);
}
imshow("result image",resultImg);
cout << "ORB执行时间为:" << t << "ms" << endl;
cout << "最小距离为:" <<minDist<< endl;
cout << "最大距离为:" << maxDist << endl;
imshow("ORB_demo", orbImg);
}
关于具体的理论部分可以参考下面两篇文章:
参考文章:https://blog.csdn.net/gaotihong/article/details/78712017
参考文章:https://blog.csdn.net/guoyunfei20/article/details/78792770