OpenCV视频追踪实例之akaze_tracking

2024-01-11 01:58

本文主要是介绍OpenCV视频追踪实例之akaze_tracking,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用AKAZE算法进行视频追踪(对比ORB算法)

简述orb与akaze算法
David. Lowe提出的SIFT算法由于卓越的性能,在过去二十多年几乎应用于目标追踪、图像匹配等相关计算机视觉领域。2012年Pablo F. Alcantarilla所提出的KAZE算法在匹配鲁棒性与速度上要优于SIFT算法;但是,KAZE算法的时间依然较高:因此原作者在13年提出Accelerated-KAZE(AKAZE)算法,在保证匹配鲁棒性的同时减少算法耗时。对比当前主要的快速ORB匹配算法,实验结果表明akaze算法从匹配性能与算法耗时都优于orb算法。

akaze算法较kaze算法改进主要在于两个方面
一、在构建非线性尺度空间时候,kaze算法采取AOS算法进行求解扩散方程,虽然稳定但是求解耗时较高,akaze算法采取快速显示扩散(FED)算法进行快速求解。附:kaze算法尺度空间不是金字塔模式,akaze算法采取金字塔方式,在提取特征点会进一步加速。
二、kaze算法采用MSURF描述符,MSURF描述符求取过程是进行特征点局部梯度求取,耗时较高。akaze算法采用的是LDB描述子(二值描述子),速度快,同时作者对LDB描述子进一步改进M-LDB描述子(更好的支持旋转的鲁棒性)。

orb算法主要是通过改进FAsT角点算法提取特征点与BRIEF二值描述子进行描述局部特征,最后进行匹配。orb算法的主要优点:速度快,性能能够满足实时性匹配要求,特别对于移动端应用。

下面为orb与akaze算法进行视频追踪的性能比较代码
主函数cpp如下(工程随后附下载地址链接)

/***********************************************************************
*            akaze_tracking.cpp : 定义控制台应用程序的入口点。
*            akaze算法对比orb算法的视频追踪demo
*            操作说明: 
*                    运行程序  视频流正常播放中....
*                    按下Enter键 用鼠标选定ROI(感兴趣区域)
*                    再次按下Enter键视频流播放...观察匹配结果
************************************************************************/
#include "stdafx.h"
#include <opencv2/features2d.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>  
#include <vector>
#include <iostream>
#include <iomanip>#include "stats.h" // 数据结构定义头文件
#include "utils.h" // 绘制和打印功能头文件using namespace std;
using namespace cv;
// akaze算法进行追踪的相关参数阈值设置
const double akaze_thresh = 3e-4; // AKAZE 检测阈值设置为1000个关键点
const double ransac_thresh = 2.5f; // RANSAC内联点阈值大小
const double nn_match_ratio = 0.8f; // 最近邻匹配阈值
const int bb_min_inliers = 10; // 设置画矩形框的最少匹配点对
const int stats_update_period = 10; // 屏幕上的统计信息每10帧更新一次namespace example {class Tracker{public:// 构造函数入口Tracker(Ptr<Feature2D> _detector, Ptr<DescriptorMatcher> _matcher) :detector(_detector),matcher(_matcher){}void setFirstFrame(const Mat frame, vector<Point2f> bb, string title, Stats& stats);Mat process(const Mat frame, Stats& stats);Ptr<Feature2D> getDetector() {return detector;}protected:Ptr<Feature2D> detector;Ptr<DescriptorMatcher> matcher;Mat first_frame, first_desc;  // 第一帧ROI区域图像   描述符矩阵vector<KeyPoint> first_kp;    // 特征点数据vector<Point2f> object_bb;    // ROI对应的四个顶点坐标};void Tracker::setFirstFrame(const Mat frame, vector<Point2f> bb, string title, Stats& stats){cv::Point *ptMask = new cv::Point[bb.size()];const Point* ptContain = { &ptMask[0] };int iSize = static_cast<int>(bb.size());for (size_t i = 0; i<bb.size(); i++) {ptMask[i].x = static_cast<int>(bb[i].x);ptMask[i].y = static_cast<int>(bb[i].y);}first_frame = frame.clone();cv::Mat matMask = cv::Mat::zeros(frame.size(), CV_8UC1);// fillPoly()函数功能可以用来填充复杂多边形轮廓的区域cv::fillPoly(matMask, &ptContain, &iSize, 1, cv::Scalar::all(255));// 检测特征点和描述符detector->detectAndCompute(first_frame, matMask, first_kp, first_desc);stats.keypoints = (int)first_kp.size();// 绘制选定ROI区域的矩形框drawBoundingBox(first_frame, bb);putText(first_frame, title, Point(0, 60), FONT_HERSHEY_PLAIN, 5, Scalar::all(0), 4);object_bb = bb;delete[] ptMask;}// 进行视频播放抽帧进行匹配过程函数......Mat Tracker::process(const Mat frame, Stats& stats){TickMeter tm;vector<KeyPoint> kp;Mat desc;tm.start();  // 计时开始detector->detectAndCompute(frame, noArray(), kp, desc); // 检测特征点与计算特征点的局部描述符stats.keypoints = (int)kp.size();vector< vector<DMatch> > matches;vector<KeyPoint> matched1, matched2;matcher->knnMatch(first_desc, desc, matches, 2);   // knnMatch进行匹配for (unsigned i = 0; i < matches.size(); i++) {   // nn_match_ratio距离阈值进行匹配if (matches[i][0].distance < nn_match_ratio * matches[i][1].distance) {matched1.push_back(first_kp[matches[i][0].queryIdx]);matched2.push_back(kp[matches[i][0].trainIdx]);}}stats.matches = (int)matched1.size();Mat inlier_mask, homography;vector<KeyPoint> inliers1, inliers2;vector<DMatch> inlier_matches;if (matched1.size() >= 4) {homography = findHomography(Points(matched1), Points(matched2),RANSAC, ransac_thresh, inlier_mask); // RANSAC算法进行提纯估计单应矩阵}tm.stop();  // 匹配结束stats.fps = 1. / tm.getTimeSec();// 若匹配点对少于4对或者单应矩阵为空if (matched1.size() < 4 || homography.empty()) {Mat res;hconcat(first_frame, frame, res);stats.inliers = 0;stats.ratio = 0;return res;}for (unsigned i = 0; i < matched1.size(); i++) {if (inlier_mask.at<uchar>(i)) {int new_i = static_cast<int>(inliers1.size());inliers1.push_back(matched1[i]);inliers2.push_back(matched2[i]);inlier_matches.push_back(DMatch(new_i, new_i, 0));}}// 匹配率stats.inliers = (int)inliers1.size();stats.ratio = stats.inliers * 1.0 / stats.matches;vector<Point2f> new_bb;// 根据匹配估计的单应矩阵 + ROI坐标计算对应视频流帧对应的ROI坐标perspectiveTransform(object_bb, new_bb, homography);Mat frame_with_bb = frame.clone();if (stats.inliers >= bb_min_inliers) {   // 若匹配点数大于设置的内联点数绘制矩形框drawBoundingBox(frame_with_bb, new_bb);}Mat res;// 匹配点对绘制drawMatches(first_frame, inliers1, frame_with_bb, inliers2,inlier_matches, res, Scalar(255, 0, 0), Scalar(255, 0, 0));return res;}
}int main(int argc, char **argv)
{// 视频输入路径参数string input_path = "..\\akaze_tracking\\video\\Megamind.avi";string video_name = input_path;VideoCapture video_in;// 视频路径判断是否正确打开if ((isdigit(input_path[0]) && input_path.size() == 1)){int camera_no = input_path[0] - '0';video_in.open(camera_no);}else {video_in.open(video_name);}if (!video_in.isOpened()) {cerr << "Couldn't open " << video_name << endl;system("pause");return 1;}// 匹配相关变量数据结构: 内联点、匹配点等Stats stats, akaze_stats, orb_stats;// AKAZE算法初始化Ptr<AKAZE> akaze = AKAZE::create();akaze->setThreshold(akaze_thresh);// ORB算法初始化Ptr<ORB> orb = ORB::create();// 匹配方式暴力汉明距离Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming");// Tracker类对象 akaze_tracker 与 orb_tracker    // Tracker(Ptr<Feature2D> _detector, Ptr<DescriptorMatcher> _matcher)example::Tracker akaze_tracker(akaze, matcher);example::Tracker orb_tracker(orb, matcher);Mat frame;namedWindow(video_name, WINDOW_NORMAL);cout << "\nPress any key to stop the video and select a bounding box" << endl;while (waitKey(1) < 1){video_in >> frame;cv::resizeWindow(video_name, frame.size());imshow(video_name, frame);}// 选取当前视频某一帧ROI区域进行获取数据vector<Point2f> bb;cv::Rect uBox = cv::selectROI(video_name, frame);// bb 为视频ROOI区域的坐标信息bb.push_back(cv::Point2f(static_cast<float>(uBox.x), static_cast<float>(uBox.y)));bb.push_back(cv::Point2f(static_cast<float>(uBox.x + uBox.width), static_cast<float>(uBox.y)));bb.push_back(cv::Point2f(static_cast<float>(uBox.x + uBox.width), static_cast<float>(uBox.y + uBox.height)));bb.push_back(cv::Point2f(static_cast<float>(uBox.x), static_cast<float>(uBox.y + uBox.height)));akaze_tracker.setFirstFrame(frame, bb, "AKAZE", stats);orb_tracker.setFirstFrame(frame, bb, "ORB", stats);Stats akaze_draw_stats, orb_draw_stats;Mat akaze_res, orb_res, res_frame;int i = 0;for (;;) {i++;// stats_update_period视频帧更新时间bool update_stats = (i % stats_update_period == 0);video_in >> frame;// 视频流播放结束(抽帧失败)if (frame.empty())break;// akaze_res 绘制匹配输出的结果akaze_res = akaze_tracker.process(frame, stats);akaze_stats += stats;if (update_stats) {akaze_draw_stats = stats;}// orb视频抽帧追踪orb->setMaxFeatures(stats.keypoints);orb_res = orb_tracker.process(frame, stats);orb_stats += stats;if (update_stats) {orb_draw_stats = stats;}// 绘制匹配点drawStatistics(akaze_res, akaze_draw_stats);drawStatistics(orb_res, orb_draw_stats);vconcat(akaze_res, orb_res, res_frame);cv::imshow(video_name, res_frame);if (waitKey(1) == 27) break; //quit on ESC button}akaze_stats /= i - 1;orb_stats /= i - 1;printStatistics("AKAZE", akaze_stats);printStatistics("ORB", orb_stats);system("pause");return 0;
}

orb与akaze算法对比实验结果图
一、首先运行程序,视频流播放窗口弹出,按下Enter键,通过鼠标选择ROI(感兴趣区域)

二、选择ROI区域后,再次按下Enter键让程序进行匹配追踪

其中:左边的为选取的ROI区域,右边为视频播放进行抽帧进行匹配(上:akaze 下:orb)。

三、最终视频播放结束,orb与akaze算法性能比较……


本机配置:windows10 64位操作系统 + visual studio2015 x64+ opencv3.3.1

若工程无法打开或者打开失败,可以新建工程将.h .cpp添置工程中,按照本工程环境配置opencv动态路径即可

百度网盘地址链接:https://pan.baidu.com/s/1kWHk8dD 密码:uizu

这篇关于OpenCV视频追踪实例之akaze_tracking的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/592776

相关文章

流媒体平台/视频监控/安防视频汇聚EasyCVR播放暂停后视频画面黑屏是什么原因?

视频智能分析/视频监控/安防监控综合管理系统EasyCVR视频汇聚融合平台,是TSINGSEE青犀视频垂直深耕音视频流媒体技术、AI智能技术领域的杰出成果。该平台以其强大的视频处理、汇聚与融合能力,在构建全栈视频监控系统中展现出了独特的优势。视频监控管理系统EasyCVR平台内置了强大的视频解码、转码、压缩等技术,能够处理多种视频流格式,并以多种格式(RTMP、RTSP、HTTP-FLV、WebS

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

opencv 滚动条

参数介绍:createTrackbar( trackbarname , "hello" , &alpha_slider ,alpha_max ,  on_trackbar )  ;在标签中显示的文字(提示滑动条的用途) TrackbarName创建的滑动条要放置窗体的名字 “hello”滑动条的取值范围从 0 到 alpha_max (最小值只能为 zero).滑动后的值存放在

android-opencv-jni

//------------------start opencv--------------------@Override public void onResume(){ super.onResume(); //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是 //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存

C++操作符重载实例(独立函数)

C++操作符重载实例,我们把坐标值CVector的加法进行重载,计算c3=c1+c2时,也就是计算x3=x1+x2,y3=y1+y2,今天我们以独立函数的方式重载操作符+(加号),以下是C++代码: c1802.cpp源代码: D:\YcjWork\CppTour>vim c1802.cpp #include <iostream>using namespace std;/*** 以独立函数

实例:如何统计当前主机的连接状态和连接数

统计当前主机的连接状态和连接数 在 Linux 中,可使用 ss 命令来查看主机的网络连接状态。以下是统计当前主机连接状态和连接主机数量的具体操作。 1. 统计当前主机的连接状态 使用 ss 命令结合 grep、cut、sort 和 uniq 命令来统计当前主机的 TCP 连接状态。 ss -nta | grep -v '^State' | cut -d " " -f 1 | sort |

《x86汇编语言:从实模式到保护模式》视频来了

《x86汇编语言:从实模式到保护模式》视频来了 很多朋友留言,说我的专栏《x86汇编语言:从实模式到保护模式》写得很详细,还有的朋友希望我能写得更细,最好是覆盖全书的所有章节。 毕竟我不是作者,只有作者的解读才是最权威的。 当初我学习这本书的时候,只能靠自己摸索,网上搜不到什么好资源。 如果你正在学这本书或者汇编语言,那你有福气了。 本书作者李忠老师,以此书为蓝本,录制了全套视频。 试

Java Websocket实例【服务端与客户端实现全双工通讯】

Java Websocket实例【服务端与客户端实现全双工通讯】 现很多网站为了实现即时通讯,所用的技术都是轮询(polling)。轮询是在特定的的时间间隔(如每1秒),由浏览器对服务器发 出HTTP request,然后由服务器返回最新的数据给客服端的浏览器。这种传统的HTTP request 的模式带来很明显的缺点 – 浏 览器需要不断的向服务器发出请求,然而HTTP