[C++]使用yolov5的onnx模型结合opencv和bytetrack实现目标追踪

作品简介

【算法介绍】

基于C++的YOLOv5、ONNXRuntime和ByteTrack目标追踪实现是一种高效的目标追踪解决方案。YOLOv5是YOLO系列算法的比较出色版本,以其出色的目标检测性能和实时性著称。ONNXRuntime是微软开发的高性能推理引擎,支持多种框架生成的ONNX格式模型,能够实现高效的模型推理。ByteTrack则是一种基于轨迹匹配的目标追踪方法,利用目标的运动信息和外观特征进行追踪,具有强大的鲁棒性和适应性。

在C++环境中,首先通过YOLOv5进行目标检测,生成目标的初始位置和运动轨迹。然后,ByteTrack利用这些信息对目标进行精确追踪。ONNXRuntime作为推理引擎,负责加载和运行YOLOv5的ONNX模型,实现高效的目标检测。

这种结合方式既发挥了YOLOv5的高检测精度,又利用了ByteTrack的高追踪精度,使得整体目标追踪效果显著提升。同时,C++的高效性能也使得该方案在实时性方面表现出色。

总的来说,基于C++的YOLOv5、ONNXRuntime和ByteTrack目标追踪实现是一种高效、准确且实时的目标追踪解决方案,适用于各种复杂场景下的目标追踪任务。

【效果展示】

【实现部分代码】

#include 

#include 

 

#include "cmdline.h"

#include "utils.h"

#include "detector.h"

 

 

int main(int argc, char* argv[])

{

    const float confThreshold = 0.3f;

    const float iouThreshold = 0.4f;

 

   

    bool isGPU =false;

    const std::string classNamesPath = "C:\\Users\\Administrator\\Desktop\\yolov5-onnxruntime-bytetrack-cplus\\weights\\coco.names";

    const std::vector classNames = utils_yolo::loadNames(classNamesPath);

    const std::string modelPath = "C:\\Users\\Administrator\\Desktop\\yolov5-onnxruntime-bytetrack-cplus\\weights\\yolov5s.onnx";

 

    if (classNames.empty())

    {

        std::cerr << "Error: Empty class names file." << std::endl;

        return -1;

    }

 

    YOLODetector detector {nullptr};

    detector = YOLODetector(modelPath, isGPU, cv::Size(640, 640));

        std::cout << "Model was initialized." << std::endl;

    std::vector result;

	cv::VideoCapture cap("D:\\car.mp4");

	int img_w = cap.get(CAP_PROP_FRAME_WIDTH);

	int img_h = cap.get(CAP_PROP_FRAME_HEIGHT);

	int fps = cap.get(CAP_PROP_FPS);

	long nFrame = static_cast(cap.get(CAP_PROP_FRAME_COUNT));

	if (!cap.isOpened())

	{

		std::cout << "open capture failured!" << std::endl;

		return -1;

	}

	Mat frame;

	BYTETracker tracker(fps, 30);

	int num_frames = 0;

	int keyvalue = 0;

    int total_ms = 1;

	while (true)

	{

		cap.read(frame);

		if (frame.empty())

		{

			std::cout << "read to end" << std::endl;

			break;

		}

		num_frames++;

		auto start = chrono::system_clock::now();

		result.clear();

		result = detector.detect(frame, confThreshold, iouThreshold);

       vector output_stracks = tracker.update(result);

		auto end = chrono::system_clock::now();

		total_ms = total_ms + chrono::duration_cast(end - start).count();

		for (int i = 0; i < output_stracks.size(); i++)

		{

			vector tlwh = output_stracks[i].tlwh;

			bool vertical = tlwh[2] / tlwh[3] > 1.6;

			if (tlwh[2] * tlwh[3] > 20 && !vertical)

			{

				Scalar s = tracker.get_color(output_stracks[i].track_id);

				putText(frame, format("%d", output_stracks[i].track_id), Point(tlwh[0], tlwh[1] - 5),

						0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);

				rectangle(frame, Rect(tlwh[0], tlwh[1], tlwh[2], tlwh[3]), s, 2);

			}

		}

		putText(frame, format("frame: %d fps: %d num: %d", num_frames, num_frames * 1000000 / total_ms, (int)output_stracks.size()),

				Point(0, 30), 0, 0.6, Scalar(0, 0, 255), 2, LINE_AA);

 

		imshow("demo", frame);

		keyvalue = waitKey(1);

		if (keyvalue == 113 || keyvalue == 81)

		{

			break;

		}

 

	}

	cap.release();

 

 

    return 0;

}

【视频演示】

【测试环境】

 opencv==4.8.0

onnxruntime==1.16.3

vs2019

cmake==3.24.3 

创作时间: