用SURF算法和其描述子实现视频的特征图像跟踪和标定
2018-01-12 17:01
399 查看
其实最初我是想采用
而且
我当前所做成的Demo也有这个问题,就是帧数过低,看起来并不流畅,但是只是对
当然,后面我会对这个特征图像的跟踪Demo进行进一步的优化,
初步方案是采用光流金字塔
opencv 2.3.1
取一帧图像
将帧图像的描述子算出并和特征图像的描述子进行对比
对比得到
绘制出匹配点
通过获取多个点的透视变化
通过前面的透视矩阵将帧图像中的特征图像圈出
准确度不高,坏点的去除不完善
SIFT的算子和特征点识别来进行特征图像的跟踪标定的,但是经过测试后发现
SIFT的检测时间实在是太长了,根本不适合作为视频的特征识别的算法,所以虽然其识别准确率是最高的,但是还是只能进行舍弃
而且
SURF虽然准确率没有
SIFT高,但其也保留了基本的尺度不变性和旋转不变型,用作特征图像的标定其实也算不错,不过这样的方法也有很大的问题,就是每一帧都必须对全局图像进行一个特征点的描述,这样会造成每一帧的计算量太大而导致掉帧的情况。
我当前所做成的Demo也有这个问题,就是帧数过低,看起来并不流畅,但是只是对
SURF的视频识别效率做一个测试,问题也不算太大
当然,后面我会对这个特征图像的跟踪Demo进行进一步的优化,
初步方案是采用光流金字塔
calcOpticalFlowPyrLK和
SURF混用的方式达到比较好的同步率,然后采用更加动态化的方式去进行对应特征点的筛选以达到更好的准确性。
运行环境
Visual Studio 2017 ( X86 Release )opencv 2.3.1
Demo实现的大致步骤
获取特征图像的描述子存入固定容器取一帧图像
将帧图像的描述子算出并和特征图像的描述子进行对比
对比得到
DMatch对象容器,并进行筛选得到较好的匹配点和其对应的位置
points(如何筛选
DMatch请看SIFT算法的特征点筛选和DMatch、Keypoint描述)
绘制出匹配点
通过获取多个点的透视变化
findHomography函数算出
points相对于原图像对应位置的透视矩阵
通过前面的透视矩阵将帧图像中的特征图像圈出
代码详情
由于注释比较详细,就不多说了,直接贴代码吧int main() { float MaxDistance = 0; //最大欧拉角 float MinDistance = 999; //最小欧拉角 //识别图像 Mat inputObj = imread("image/img2.jpg", 1); //场景图像 Mat inputScene; //两者的灰度图像 Mat imgGrayObj, imgGrayScene; //转换灰度图 cvtColor(inputObj, imgGrayObj, CV_BGR2GRAY); //SURF特征检测 SurfFeatureDetector detector; //特征点容器 vector<KeyPoint> keypointsObj, keypointsScene; //找出特征图像的特征点 detector.detect(imgGrayObj, keypointsObj); //surf描述子 SurfDescriptorExtractor extractor; //描述子矩阵 Mat descriptorObj, descriptorScene; //匹配器 BruteForceMatcher<L2<float>> matcher; //匹配得到的DMatch容器 vector<DMatch> matches; extractor.compute(imgGrayObj, keypointsObj, descriptorObj); VideoCapture camera(0);//初始化摄像头,0代表默认摄像头 vector<DMatch> matchesVoted;//选出的优质匹配 vector<Point2f> points1, points2;//对应点的位置 vector<KeyPoint> imagePoints1, imagePoints2;//选出的对应优质特征点 while (true) { if (!camera.isOpened()) { cerr << "open camera error" << endl; break; } camera >> inputScene;//获取当前帧 //灰度化图像 cvtColor(inputScene, imgGrayScene, CV_BGR2GRAY); //找出特征点 detector.detect(imgGrayScene, keypointsScene); extractor.compute(imgGrayScene, keypointsScene, descriptorScene); matcher.match(descriptorObj, descriptorScene, matches); //得到匹配的最大最小欧拉距离 for (int i = 0; i < matches.size(); i++) { if (matches[i].distance > MaxDistance) { MaxDistance = matches[i].distance; } if (matches[i].distance < MinDistance) { MinDistance = matches[i].distance; } } int count = 0; //筛选特征点 for (int i = 0; i < matches.size(); i++) { if (matches[i].distance <= 2.8 * MinDistance) { DMatch dmatch; dmatch.queryIdx = count; dmatch.trainIdx = count; dmatch.distance = matches[i].distance; matchesVoted.push_back(dmatch); imagePoints1.push_back(keypointsObj[matches[i].queryIdx]); imagePoints2.push_back(keypointsScene[matches[i].trainIdx]); points1.push_back(keypointsObj[matches[i].queryIdx].pt); points2.push_back(keypointsScene[matches[i].trainIdx].pt); count++; } } Mat img_matches; drawMatches(inputObj, imagePoints1, inputScene, imagePoints2, matchesVoted, img_matches, DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); if (points1.size() >= 4) {//是否具备进行透视矩阵变换的基础 //透视变换 Mat h = findHomography(points1, points2, CV_RANSAC); std::vector<Point2f> obj_corners(4); //特征图像中的四个顶点位置 obj_corners[0] = cvPoint(0, 0); obj_corners[1] = cvPoint(imgGrayObj.cols, 0); obj_corners[2] = cvPoint(imgGrayObj.cols, imgGrayObj.rows); obj_corners[3] = cvPoint(0, imgGrayObj.rows); std::vector<Point2f> scene_corners(4); //透视变换将顶点位置转换成帧图像中的位置 perspectiveTransform(obj_corners, scene_corners, h); //画矩阵 line(img_matches, scene_corners[0] + Point2f(imgGrayObj.cols, 0), scene_corners[1] + Point2f(imgGrayObj.cols, 0), Scalar(0, 255, 0), 4); line(img_matches, scene_corners[1] + Point2f(imgGrayObj.cols, 0), scene_corners[2] + Point2f(imgGrayObj.cols, 0), Scalar(0, 255, 0), 4); line(img_matches, scene_corners[2] + Point2f(imgGrayObj.cols, 0), scene_corners[3] + Point2f(imgGrayObj.cols, 0), Scalar(0, 255, 0), 4); line(img_matches, scene_corners[3] + Point2f(imgGrayObj.cols, 0), scene_corners[0] + Point2f(imgGrayObj.cols, 0), Scalar(0, 255, 0), 4); } imshow("SURF_Match_Image", img_matches); //清理场景特征点容器 matches.clear(); keypointsScene.clear(); matchesVoted.clear(); points1.clear(); points2.clear(); imagePoints1.clear(); imagePoints2.clear(); waitKey(33); } return 0; }
效果展示
缺点
效率太低,帧率太低,应该只有10帧左右准确度不高,坏点的去除不完善
相关文章推荐
- 图像特征检测描述(一):SIFT、SURF、ORB、HOG、LBP特征的原理概述及OpenCV代码实现
- 【图像特征提取12】OpenCv的SIFT图像局部特征提取描述算法C++代码的实现
- 利用SURF特征检测和FLANN最近邻算法实现图像的目标提取
- 【OpenCV】SURF算法之视频图像实时特征点匹配
- MATLAB GUI实现常见图像处理算法与视频跟踪算法
- 图像特征描述SIFT、SURF、ORB、HOG、HAAR、LBP特征的原理概述
- Opencv3 Sift和Surf特征实现图像无缝拼接生成全景图像
- 利用opencv2.4.10+VS2012和RobHess的sift特征算法实现全景图像拼接
- Opencv下利用SIFT、SURF、ORB三种特征点实现图像匹配
- 视频跟踪之均值漂移算法的实现
- 【图像特征提取7】SURF特征提取算法的
- Opencv Sift和Surf特征实现图像无缝拼接生成全景图像
- Python图像特征检测算法(1):Python实现SIFT和Harris
- SVM中图像常用的HOG特征描述及实现
- 特征检测、描述、匹配,视频跟踪,物体识别
- Opencv Sift和Surf特征实现图像无缝拼接生成全景图像
- 图像算法之四:特征提取算法之SURF
- Opencv Sift和Surf特征实现图像无缝拼接生成全景图像
- 基于ORB特征提取算法图像匹配 python实现
- Opencv Sift和Surf特征实现图像无缝拼接生成全景图像