实时性特征检测
可以分为两个部分:图像特征提取与匹配
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