yolov5+deepsort目标检测与跟踪

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

关于yolov5+deepsort实现目标检测与跟踪中deepsort特征提取的一种折中方法C++


前言

提示:这里可以添加本文要记录的大概内容:

deepsort是一种基于深度学习的多目标跟踪算法,主要原理本文不再描述,网上内容较多,个人理解其主要思想是在传统的sort算法的基础上,添加一块待跟踪目标的特征信息,即目标的feature,这样在后续进行关联匹配的时候能提升准确率。目前网上较多的资源是基于https://github.com/RichardoMrMu/yolov5-deepsort-tensorrt这位大神提供开源程序,他的tensorrt为7的版本,最近由于项目中需要添加这个deepsort,但是开发的机器刚装完tensorrt8,实在不想捣鼓环境版本,又结合Tensorrt大佬提供的项目https://github.com/shouxieai/tensorRT_Pro/,其中关于人脸跟踪的程序,本文想出了一个比较折中的方案,借助OpenCV的DNN实现deepsort的feature抽取(主要是目前技术水平太菜了,对于Tensorrt的掌握还不够,只能用这种折中的方法先应付项目),最终效果还可以,关于借助Tensorrt部署yolov5,本文并不再描述,网上资源较多,本文只描述如何使用OpenCV的DNN实现deepsort的feature抽取。


提示:以下是本篇文章正文内容,下面案例可供参考

一、开发环境

Ubuntu18.04 + CUDA11.0 + cuDNN8.2 + TensorRT8.2 + OpenCV4.5.3
在安装OpenCV的过程中,需要将CUDA加速的部分编译进去,安装教程网上较多,可以先安装cmake-gui方便安装过程中配置,具体安装可以自行百度。

二、开始实战

1.将deepsort权重导出为.onnx

首先需要将deepsort算法中的权重文件导出为.onnx的格式
通过如下指令下载相关的开源程序

git clone https://github.com/RichardoMrMu/deepsort-tensorrt.git

然后进入到下载到的程序中,运行exportOnnx.py即可将deepsort的权重ckpt.t7转换为.onnx,在转换的过程中,请先看一下程序的内容,避免转换过程出错,转换完成之后,会生成一个deepsort.onnx的文件,将该文件复制到你的yolov5+deepsort工程文件夹中即可。

python3 exportOnnx.py

这个deepsort的权重ckpt.t7可以在下面链接中找到并下载
https://github.com/ZQPei/deep_sort_pytorch

2.主要程序

完成了上述权重的转换之后,即可通过如下的程序抽取到待跟踪目标的feature了,可以将此段程序添加进你的yolov5目标检测中,实现yolov5+deepsort目标检测与跟踪。

/** OpenCV一些头文件 */
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/cuda.hpp>
......
int main(int argc, char** argv)
{
         ......
	   /** OpenCV DNN加载deepsort权重 */
       cv::String deepsort_onnx = "/home/xx/xx/xx/xx/xx/deepsort.onnx";    // 存放deepsort.onnx的路径
       const int inpWidth = 64;        // 设置网络的输入width
       const int inpHeight = 128;    // 设置网络的输入height
       cv::dnn::Net net;
       net = cv::dnn::readNet(deepsort_onnx);
       net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);    
       net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);    // 设置OpenCV的后端为CUDA,开启CUDA加速
       ......
       std::vector<DeepSORT::Box> boxes;
       DeepSORT::Box track_box;
       cv::Rect feature_track;             // deepsort跟踪时的feature特征
       cv::Mat feature_image;
       .......
       /** 加入目标跟踪 */
       track_box.left = result.left;
       track_box.top = result.top;
       track_box.right = result.right;
       track_box.bottom = result.bottom;
 #ifdef DEBUG
       printf("track_box.left=%.2f, track_box.top=%.2f, track_box.right=%.2f, track_box.bottom=%.2f", track_box.left, track_box.top, track_box.right, track_box.bottom);
#endif
       // 这边的判断条件可以简化一下,主要防止目标框出现在frame的外侧,这样后面扣图的时候会失败。
       if ((track_box.left > 0 && track_box.top > 0 && track_box.right > 0 && track_box.bottom > 0) && 
           (track_box.left < frame.cols && track_box.top < frame.rows && track_box.right < frame.cols && track_box.bottom < frame.rows)) 
       {
           feature_track = cv::Rect(result.left, result.top, (result.right - result.left), (result.bottom - result.top));    // 获取目标跟踪的feature
           feature_image = frame(feature_track);    
           cv::Mat blob;
           cv::dnn::blobFromImage(feature_image, blob, 1 / 255.0, cv::Size(inpWidth, inpHeight), cv::Scalar(0, 0, 0), true, false);
           net.setInput(blob);
           std::vector<cv::Mat> outs;
           net.forward(outs, net.getUnconnectedOutLayersNames());
#ifdef DEBUG
           std::cout << "+++++ outs.size=" << outs.size() << "+++++" << std::endl;
#endif
           track_box.feature = outs[0];
           boxes.push_back(track_box);
       }
       ......
       /** deepsort更新 */
       tracker->update(boxes);
       ......
       // 绘制结果图
       ......
}

总结

第一次写CSDN的文章,有点生疏,难免有点错误,希望各位看到的时候能够在下方评论指正,谢谢!大家有什么想法也可以在评论区评论交流。其实,本文也只是记录一下本人在项目实际开发的过程中想到的一个想法,并且实际操作了一下,如果对你的项目开发能起到一丁点的帮助,我将无比荣幸!其实,从deepsort的权重中可以看出,最终输出的是一个1x512的特征矩阵,在实际跟踪的时候,获取到了这个特征矩阵,并将其做一个转置矩阵,得到一个512x1的矩阵,两个一乘就有了一个值,通过这个值就加强了目标跟踪中的匹配准确性。在上方,本文说了,这个方法是由于本人技术太菜,并未完全掌握TensorRT想出来的一个折中方法,结合deepsort的原理,这个目标的feature其实在yolo检测目标的时候已经获得过了,那么我们能不能在yolo检测目标的时候,顺带把这个feature一并输出,就是说在推理yolo的时候,除了获得一个boundingbox,顺带再获得一个跟这个boundingbox相匹配的feature,相当于在程序中我最终输出的result的结构体中还包含一个feature的成员,这个feature只要是个1xn的矩阵即可,反正后面会做一个转置运算,当然了,这只是本人的一个想法,也不知道行不行,等后续掌握了TensortRT之后,再魔改一下yolo的推理程序,试试看看,本文先到此为止,感谢阅读!

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>