两百行C++代码实现yolov5车辆计数部署(通俗易懂版)

这篇具有很好参考价值的文章主要介绍了两百行C++代码实现yolov5车辆计数部署(通俗易懂版)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文是文章传统图像处理方法实现车辆计数的后续。这里用OpenCV实现了基于yolov5检测器的单向车辆计数功能,方法是撞线计数。该代码只能演示视频demo效果,一些功能未完善,离实际工程应用还有距离。
实现流程:
(1)训练yolov5模型,这里就没有自己训练了,直接使用官方的开源模型yolov5s.pt;
(2)运行yolov5工程下面的export.py,将pt模型转成onnx模型;
(3)编写yolov5部署的C++工程,包括前处理、推理和后处理部分;
(4)读取视频第一帧,用yolov5检测第一帧图像的车辆目标,计算这些检测框的中心点,
(5)读取视频的后续帧,用yolov5检测每帧图像上的车辆目标,计算新目标和上一帧图像中检测框中心点的距离矩阵;
(6)通过距离矩阵确定新旧目标检测框之间的对应关系;
(7)计算对应新旧目标检测框中心点之间的连线,判断和事先设置的虚拟撞线是否相交,若相交则计数加1;
(8)重复(5)-(7)。
由于程序在CPU端运行,为了提速,实际实现的时候采取的是隔帧判断而不是使用相邻帧,v1的代码实现如下:

#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>


// 常量
const float INPUT_WIDTH = 640.0;
const float INPUT_HEIGHT = 640.0;
const float SCORE_THRESHOLD = 0.5;
const float NMS_THRESHOLD = 0.45;
const float CONFIDENCE_THRESHOLD = 0.45;

const std::vector<std::string> class_name = {
"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
"hair drier", "toothbrush" };


// 画框函数
void draw_label(cv::Mat& input_image, std::string label, int left, int top)
{
	int baseLine;
	cv::Size label_size = cv::getTextSize(label, 0.7, 0.7, 1, &baseLine);
	top = std::max(top, label_size.height);
	cv::Point tlc = cv::Point(left, top);
	cv::Point brc = cv::Point(left , top + label_size.height + baseLine);
	cv::putText(input_image, label, cv::Point(left, top + label_size.height), cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 255, 255), 1);
}


// 预处理
std::vector<cv::Mat> preprocess(cv::Mat& input_image, cv::dnn::Net& net)
{
	cv::Mat blob;
	cv::dnn::blobFromImage(input_image, blob, 1. / 255., cv::Size(INPUT_WIDTH, INPUT_HEIGHT), cv::Scalar(), true, false);

	net.setInput(blob);

	std::vector<cv::Mat> preprcess_image;
	net.forward(preprcess_image, net.getUnconnectedOutLayersNames());

	return preprcess_image;
}


// 后处理
std::vector<cv::Rect> postprocess(std::vector<cv::Mat>& preprcess_image, cv::Mat& output_image)
{
	std::vector<int> class_ids;
	std::vector<float> confidences;
	std::vector<cv::Rect> boxes;
	std::vector<cv::Rect> boxes_nms;

	float x_factor = output_image.cols / INPUT_WIDTH;
	float y_factor = output_image.rows / INPUT_HEIGHT;

	float* data = (float*)preprcess_image[0].data;

	const int dimensions = 85;
	const int rows = 25200;
	for (int i = 0; i < rows; ++i)
	{
		float confidence = data[4];
		if (confidence >= CONFIDENCE_THRESHOLD)
		{
			float* classes_scores = data + 5;
			cv::Mat scores(1, class_name.size(), CV_32FC1, classes_scores);
			cv::Point class_id;
			double max_class_score;
			cv::minMaxLoc(scores, 0, &max_class_score, 0, &class_id);
			if (max_class_score > SCORE_THRESHOLD)
			{
				confidences.push_back(confidence);
				class_ids.push_back(class_id.x);

				float cx = data[0];
				float cy = data[1];
				float w = data[2];
				float h = data[3];
				int left = int((cx - 0.5 * w) * x_factor);
				int top = int((cy - 0.5 * h) * y_factor);
				int width = int(w * x_factor);
				int height = int(h * y_factor);
				boxes.push_back(cv::Rect(left, top, width, height));
			}
		}
		data += 85;
	}

	std::vector<int> indices;
	cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
	for (size_t i = 0; i < indices.size(); i++)
	{
		int idx = indices[i];
		cv::Rect box = boxes[idx];
		boxes_nms.push_back(box);

		int left = box.x;
		int top = box.y;
		int width = box.width;
		int height = box.height;
		cv::rectangle(output_image, cv::Point(left, top), cv::Point(left + width, top + height), cv::Scalar(255, 0, 0), 1);

		std::string label = cv::format("%.2f", confidences[idx]);
		label = class_name[class_ids[idx]] + ":" + label;
		draw_label(output_image, label, left, top);
	}
	return boxes_nms;
}


std::vector<cv::Point> get_centers(std::vector<cv::Rect> detections)
{
	std::vector<cv::Point> detections_centers(detections.size());
	for (size_t i = 0; i < detections.size(); i++)
	{
		detections_centers[i] = cv::Point(detections[i].x + detections[i].width / 2, detections[i].y + detections[i].height / 2);
	}

	return detections_centers;
}


float get_distance(cv::Point p1, cv::Point p2)
{
	return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
}


bool is_cross(cv::Point p1, cv::Point p2)
{
	if (p1.x == p2.x) return false;

	int y = 500;  //line1: y = 500
	float k = (p1.y - p2.y) / (p1.x - p2.x);  //
	float b = p1.y - k * p1.x; //line2: y = kx + b
	float x = (y - b) / k;
	return (x > std::min(p1.x, p2.x) && x < std::max(p1.x, p2.x));
}


int main(int argc, char** argv)
{
	cv::VideoCapture capture("test.mp4");
	cv::Mat frame;
	cv::dnn::Net net = cv::dnn::readNet("yolov5s-f32.onnx");

	int frame_num = 0;
	int count = 0;
	std::vector<cv::Point> detections_centers_old;
	std::vector<cv::Point> detections_centers_new;

	while(cv::waitKey(1) < 0)
	{
	    capture >> frame;
		if (frame.empty())
			break;

		std::cout << "******************************************************************* frame_num: " << frame_num << std::endl;

		cv::Mat image = frame.clone();
		std::vector<cv::Mat> preprcess_image = preprocess(image, net);

		std::vector<cv::Rect> detections = postprocess(preprcess_image, image);

		if (frame_num == 0)
		{
			detections_centers_old = get_centers(detections);

			std::cout << "detections_center:" << std::endl;
			for (size_t i = 0; i < detections_centers_old.size(); i++)
			{
				std::cout << detections_centers_old[i] << std::endl;
			}
		}
		else if (frame_num % 2 == 0)
		{
			detections_centers_new = get_centers(detections);

			std::cout << "detections_center:" << std::endl;
			for (size_t i = 0; i < detections_centers_new.size(); i++)
			{
				std::cout << detections_centers_new[i] << std::endl;
			}

			std::vector<std::vector<float>> distance_matrix(detections_centers_new.size(), std::vector<float>(detections_centers_old.size()));
			std::cout << "distance_matrix:" << std::endl;
			for (size_t i = 0; i < detections_centers_new.size(); i++)
			{
				for (size_t j = 0; j < detections_centers_old.size(); j++)
				{
					distance_matrix[i][j] = get_distance(detections_centesr_new[i], detections_centers_old[j]); //
					std::cout << distance_matrix[i][j] << " ";
				}
				std::cout << std::endl;
			}

			std::cout << "min_index:" << std::endl;
			std::vector<float> min_indices(detections_centers_new.size());
			for (size_t i = 0; i < detections_centers_new.size(); i++)
			{
				std::vector<float> distance_vector = distance_matrix[i];
				int min_index = std::min_element(distance_vector.begin(), distance_vector.end()) - distance_vector.begin();
				min_indices[i] = min_index;
				std::cout << min_index << " ";
			}
			std::cout << std::endl;

			for (size_t i = 0; i < detections_centers_new.size(); i++)
			{
				cv::Point p1 = detections_centers_new[i];
				cv::Point p2 = detections_centers_old[min_indices[i]];
				std::cout << p1 << " " << p2 << std::endl;

				if (is_cross(p1, p2))
				{
					std::cout << "is_cross" << p1 << " " << p2 << std::endl;
					count++;
				}
			}
			detections_centers_old = detections_centers_new;
		}

		frame_num++;

		cv::putText(image, "car num: " + std::to_string(count), cv::Point(20, 50), cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 255, 255), 1);
		cv::line(image, cv::Point(0, 500), cv::Point(1280, 500) , cv::Scalar(0, 0, 255));
		cv::imshow("output", image);
		cv::imwrite(std::to_string(frame_num) + ".jpg", image);
	}

	capture.release();
	return 0;
}

在调试中,发现v1的实现存在如下问题:出现新目标的时候,计算新旧检测框的对应关系出现匹配错误,导致计数偏多。因此在v2中设置匹配的距离阈值,并简化了判断检测框中心点连线和撞线是否相交的方法。
v2的代码实现如下:

#include <iostream>
#include <opencv2/opencv.hpp>


//#define DEBUG


// 常量
const float INPUT_WIDTH = 640.0;
const float INPUT_HEIGHT = 640.0;
const float SCORE_THRESHOLD = 0.5;
const float NMS_THRESHOLD = 0.25;
const float CONFIDENCE_THRESHOLD = 0.5;

const std::vector<std::string> class_name = {
	"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",
	"fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",
	"elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",
	"skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",
	"tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",
	"sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",
	"potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",
	"microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",
	"hair drier", "toothbrush" };

const int IMAGE_WIDTH = 1280;
const int IMAGE_HEIGHT = 720;
const int LINE_HEIGHT = IMAGE_HEIGHT / 2;


//画出检测框和标签
void draw_label(cv::Mat& input_image, std::string label, int left, int top)
{
	int baseLine;
	cv::Size label_size = cv::getTextSize(label, 0.7, 0.7, 1, &baseLine);
	top = std::max(top, label_size.height);
	cv::Point tlc = cv::Point(left, top);
	cv::Point brc = cv::Point(left , top + label_size.height + baseLine);
	cv::putText(input_image, label, cv::Point(left, top + label_size.height), cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 255, 255), 1);
}


//预处理
std::vector<cv::Mat> preprocess(cv::Mat& input_image, cv::dnn::Net& net)
{
	cv::Mat blob;
	cv::dnn::blobFromImage(input_image, blob, 1. / 255., cv::Size(INPUT_WIDTH, INPUT_HEIGHT), cv::Scalar(), true, false);

	net.setInput(blob);

	std::vector<cv::Mat> preprcess_image;
	net.forward(preprcess_image, net.getUnconnectedOutLayersNames());

	return preprcess_image;
}


//后处理
std::vector<cv::Rect> postprocess(std::vector<cv::Mat>& preprcess_image, cv::Mat& output_image)
{
	std::vector<int> class_ids;
	std::vector<float> confidences;
	std::vector<cv::Rect> boxes;
	std::vector<cv::Rect> boxes_nms;

	float x_factor = output_image.cols / INPUT_WIDTH;
	float y_factor = output_image.rows / INPUT_HEIGHT;

	float* data = (float*)preprcess_image[0].data;

	const int dimensions = 85;
	const int rows = 25200;
	for (int i = 0; i < rows; ++i)
	{
		float confidence = data[4];
		if (confidence >= CONFIDENCE_THRESHOLD)
		{
			float* classes_scores = data + 5;
			cv::Mat scores(1, class_name.size(), CV_32FC1, classes_scores);
			cv::Point class_id;
			double max_class_score;
			cv::minMaxLoc(scores, 0, &max_class_score, 0, &class_id);
			if (max_class_score > SCORE_THRESHOLD)
			{
				confidences.push_back(confidence);
				class_ids.push_back(class_id.x);

				float cx = data[0];
				float cy = data[1];
				float w = data[2];
				float h = data[3];
				int left = int((cx - 0.5 * w) * x_factor);
				int top = int((cy - 0.5 * h) * y_factor);
				int width = int(w * x_factor);
				int height = int(h * y_factor);
				boxes.push_back(cv::Rect(left, top, width, height));
			}
		}
		data += 85;
	}

	std::vector<int> indices;
	cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
	for (size_t i = 0; i < indices.size(); i++)
	{
		int idx = indices[i];
		cv::Rect box = boxes[idx];
		boxes_nms.push_back(box);

		int left = box.x;
		int top = box.y;
		int width = box.width;
		int height = box.height;
		cv::rectangle(output_image, cv::Point(left, top), cv::Point(left + width, top + height), cv::Scalar(255, 0, 0), 1);

		std::string label = cv::format("%.2f", confidences[idx]);
		//label = class_name[class_ids[idx]] + ":" + label;
		label = "car";
		draw_label(output_image, label, left, top);
	}

	return boxes_nms;
}


//计算检测框的中心
std::vector<cv::Point> get_centers(std::vector<cv::Rect> detections)
{
	std::vector<cv::Point> detections_centers(detections.size());
	for (size_t i = 0; i < detections.size(); i++)
	{
		detections_centers[i] = cv::Point(detections[i].x + detections[i].width / 2, detections[i].y + detections[i].height / 2);
	}

	return detections_centers;
}


//计算两点间距离
float get_distance(cv::Point p1, cv::Point p2)
{
	return sqrt(pow(p1.x - p2.x, 2) + pow(p1.y - p2.y, 2));
}


//判断连接相邻两帧对应检测框中心的线段是否与红线相交
bool is_cross(cv::Point p1, cv::Point p2)
{
	return (p1.y <= LINE_HEIGHT && p2.y > LINE_HEIGHT) || (p1.y > LINE_HEIGHT && p2.y <= LINE_HEIGHT);
}


int main(int argc, char** argv)
{
	cv::VideoCapture capture("test.mp4");
	cv::Mat frame;
	cv::dnn::Net net = cv::dnn::readNet("yolov5s-f32.onnx");

	int frame_num = 0;
	int count = 0;
	std::vector<cv::Point> detections_centers_old;
	std::vector<cv::Point> detections_centers_new;

	while(cv::waitKey(1) < 0)
	{
	    capture >> frame;
		if (frame.empty())
			break;

		std::cout << "******************************************************************* frame_num: " << frame_num << std::endl;

		cv::Mat image = frame.clone();
		std::vector<cv::Mat> preprcess_image = preprocess(image, net);

		std::vector<cv::Rect> detections = postprocess(preprcess_image, image);

		if (frame_num == 0)
		{
			detections_centers_old = get_centers(detections);

#ifdef DEBUG
			std::cout << "detections_center:" << std::endl;
			for (size_t i = 0; i < detections_centers_old.size(); i++)
			{
				std::cout << detections_centers_old[i] << std::endl;
			}
#endif // DEBUG
		}
		else if (frame_num % 2 == 0)
		{
			detections_centers_new = get_centers(detections);

#ifdef DEBUG
			std::cout << "detections_center:" << std::endl;
			for (size_t i = 0; i < detections_centers_new.size(); i++)
			{
				std::cout << detections_centers_new[i] << std::endl;
			}
#endif // DEBUG

			std::vector<std::vector<float>> distance_matrix(detections_centers_new.size(), std::vector<float>(detections_centers_old.size())); //距离矩阵
			for (size_t i = 0; i < detections_centers_new.size(); i++)
			{
				for (size_t j = 0; j < detections_centers_old.size(); j++)
				{
					distance_matrix[i][j] = get_distance(detections_centers_new[i], detections_centers_old[j]); 
				}
			}

#ifdef DEBUG
			std::cout << "min_index:" << std::endl;
#endif // DEBUG

			std::vector<float> min_indices(detections_centers_new.size());
			for (size_t i = 0; i < detections_centers_new.size(); i++)
			{
				std::vector<float> distance_vector = distance_matrix[i];
				float min_val = *std::min_element(distance_vector.begin(), distance_vector.end());
				int min_index = -1;
				if (min_val < LINE_HEIGHT / 5)
					 min_index = std::min_element(distance_vector.begin(), distance_vector.end()) - distance_vector.begin();
				
				min_indices[i] = min_index;
#ifdef DEBUG
				std::cout << min_index << " ";
#endif // DEBUG
			}
			std::cout << std::endl;

			for (size_t i = 0; i < detections_centers_new.size(); i++)
			{
				if (min_indices[i] < 0)
					continue;

				cv::Point p1 = detections_centers_new[i];
				cv::Point p2 = detections_centers_old[min_indices[i]];

#ifdef DEBUG
				std::cout << p1 << " " << p2 << std::endl;
#endif // DEBUG

				if (is_cross(p1, p2))
				{
#ifdef DEBUG
					std::cout << "is_cross" << p1 << " " << p2 << std::endl;
#endif // DEBUG
					count++;
				}
			}

			detections_centers_old = detections_centers_new;
		}

		cv::putText(image, "car num: " + std::to_string(count), cv::Point(20, 50), cv::FONT_HERSHEY_SIMPLEX, 0.7, cv::Scalar(0, 0, 255), 1);
		cv::line(image, cv::Point(0, LINE_HEIGHT), cv::Point(IMAGE_WIDTH, LINE_HEIGHT), cv::Scalar(0, 0, 255));
		cv::imshow("output", image);

#ifdef DEBUG
		if (frame_num % 2 == 0)
			cv::imwrite(std::to_string(frame_num) + ".jpg", image);
#endif // DEBUG

		frame_num++;
	}

	capture.release();
	return 0;
}

检测效果如下图,效果还是可以的,比传统方法有大幅提升。完整视频中有一次计数异常(总共52辆向图像上方行驶的车辆,检出53辆),是因为检测器不准导致车辆检测框位置漂移,可以后续优化。注:由于官方提供的coco80类的开源权重文件用于车辆检测效果不是很好,LZ把检测出的类别直接固定为car,实际应自己重新训练一个车辆检测的模型。
两百行C++代码实现yolov5车辆计数部署(通俗易懂版)

更详细注释的代码、测试视频和转好的权重文件放在下载链接:点击跳转

后续文章:
目标跟踪算法实现车辆计数
五十行python代码实现yolov8车辆计数文章来源地址https://www.toymoban.com/news/detail-459576.html

到了这里,关于两百行C++代码实现yolov5车辆计数部署(通俗易懂版)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • YOLOv5车辆测距实践:利用目标检测技术实现车辆距离估算

    YOLOv5目标检测技术进行车辆测距。相信大家对YOLOv5已经有所了解,它是一种快速且准确的目标检测算法。接下来,让我们一起探讨如何通过YOLOv5实现车辆距离估算。这次的实践将分为以下几个步骤: 安装所需库和工具 数据准备 模型训练 距离估算 可视化结果 优化 1. 安装所需

    2024年02月02日
    浏览(52)
  • 基于YOLOv5的视频计数 — 汽车计数实现

    在视频中计数对象可能看起来有挑战性,但借助Python和OpenCV的强大功能,变得令人意外地易于实现。在本文中,我们将探讨如何使用YOLO(You Only Look Once)目标检测模型在视频流或文件中计数对象。我们将该过程分解为简单的步骤,使初学者能够轻松跟随。 本文将分为以下几

    2024年02月04日
    浏览(42)
  • YOLOv5实现目标计数

    本文主要讲解如何使用YOLOv5实现目标计数。 在detect.py文件中这部分内容替换为下面代码: 原理比较简单,就是计算锚框数量,每打印一个框count计数+1(但是值得一提的是,这种方法是不区分类别的,后续我想办法按照类进行计数)。其中label变量记录需要展示的变量,原来

    2024年02月11日
    浏览(42)
  • yolov5分割+检测c++ qt 中部署,以opencv方式(详细代码(全)+复制可用)

    1:版本说明: qt 5.12.10 opencv 4.5.3 (yolov5模型部署要求opencv4.5.0) 2:检测的代码 yolo.h yolo.cpp 检测的调用代码测试案例 这段调用的例子,只要把frame 改成你们自己的图片即可 4:分割的主要代码 YoloSeg.h YoloSeg.cpp yolov5_seg_utils.h  yolov5_seg_utils.cpp 分割的调用代码测试案例  分割的

    2024年02月03日
    浏览(43)
  • OpenCV与AI深度学习 | 实战 | 基于YOLOv9和OpenCV实现车辆跟踪计数(步骤 + 源码)

    本文来源公众号“ OpenCV与AI深度学习 ”,仅用于学术分享,侵权删,干货满满。 原文链接:实战 | 基于YOLOv9和OpenCV实现车辆跟踪计数(步骤 + 源码)     本文主要介绍使用YOLOv9和OpenCV实现车辆跟踪计数(步骤 + 源码)。      监控摄像头可以有效地用于各种场景下的车辆

    2024年04月15日
    浏览(55)
  • Opencv C++实现yolov5部署onnx模型完成目标检测

    头文件 命名空间 结构体 Net_config 里面存了三个阈值和模型地址,其中 置信度 ,顾名思义,看检测出来的物体的精准度。以测量值为中心,在一定范围内,真值出现在该范围内的几率。 endsWith()函数 判断sub是不是s的子串 anchors_640图像接收数组 根据图像大小,选择相应长度的

    2024年02月13日
    浏览(41)
  • yolov5无人机视频检测与计数系统(创新点和代码)

    标题:基于YOLOv5的无人机视频检测与计数系统 无人机技术的快速发展和广泛应用给社会带来了巨大的便利,但也带来了一系列的安全隐患。为了实现对无人机的有效管理和监控,本文提出了一种基于YOLOv5的无人机视频检测与计数系统。该系统通过使用YOLOv5目标检测算法,能够

    2024年02月02日
    浏览(56)
  • YOLOv5实现目标分类计数并显示在图像上

            有同学后台私信我,想用YOLOv5实现目标的分类计数,因此本文将在之前目标计数博客的基础上添加一些代码,实现分类计数。阅读本文前请先看那篇博客,链接如下: YOLOv5实现目标计数_Albert_yeager的博客         以coco数据集为例,其类别如下(共80类)。注意,每个

    2024年02月08日
    浏览(82)
  • 基于YOLOv5、v7、v8的竹签计数系统的设计与实现

    该系统是一个综合型的应用,基于PyTorch框架的YOLOv5、YOLOv7和YOLOv8,结合了Django后端和Vue3前端,为竹签生成工厂和串串香店铺提供了一套全面而强大的实时监测与分析解决方案。系统主要特色在于实时目标检测和位置追踪,支持用户通过上传图片、视频或摄像头进行推理,实

    2024年01月23日
    浏览(60)
  • 谈yolov5车辆识别

    目录 **前言** 一、YOLOv5算法简介 二、YOLOv5在车辆识别中的应用 1.  车辆检测

    2024年02月04日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包