C++ 调用yolov4对图片,视频,rtsp流的检测(精简版)

前篇:https://blog.csdn.net/qq_34717531/article/details/107756808

代码太多,比较繁杂,不易学习,参考:https://blog.csdn.net/m0_50117360/article/details/108131860

并做了修改,保留原有功能(调用yolov4对图片,视频,rtsp流的检测),代码进行了精简。

yolov4.cpp:

#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <vector>
#include <fstream>
#include "yolo_v2_class.hpp"

using namespace std;
using namespace cv;
#define GPU

//画出检测框和相关信息
//vector:容器,vector<string> classes:表示这个集合对象保存的是string型数据
void DrawBoxes(Mat &frame, vector<string> classes, int classId, float conf, int left, int top, int right, int bottom)
{
	//画检测框
	rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 178, 50), 3);
	//该检测框对应的类别和置信度
	string label = format("%.2f", conf);
        //如果这个类不为空,即检测到东西了
	if (!classes.empty())
	{
                //CV_Assert():若括号中表达式的值为false,则返回错误
		CV_Assert(classId < (int)classes.size());
                //类名和置信度
		label = classes[classId] + ":" + label;
	}
	//将标签显示在检测框顶部
	int baseLine;
	Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
	top = max(top, labelSize.height);
        //画框
	rectangle(frame, Point(left, top - round(1.5*labelSize.height)), Point(left + round(1.5*labelSize.width), top + baseLine), Scalar(255, 255, 255), FILLED);
        //标签
	putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 0), 1);
}


//画出检测结果
void Drawer(Mat &frame, vector<bbox_t> outs, vector<string> classes)
{
	//获取所有最佳检测框信息
	for (int i = 0; i < outs.size(); i++)
	{
		DrawBoxes(frame, classes, outs[i].obj_id, outs[i].prob, outs[i].x, outs[i].y,
			outs[i].x + outs[i].w, outs[i].y + outs[i].h);
	}
}


int main(void)
{
	string classesFile = "./cfg/coco.names";
	string modelConfig = "./cfg/yolov4.cfg";
	string modelWeights = "./cfg/yolov4.weights";
        string filename;

	//加载类别名
	vector<string> classes;
	ifstream ifs(classesFile.c_str());
	string line;
	while (getline(ifs, line)) classes.push_back(line);
	//加载网络模型,0是指定第一块GPU
	Detector detector(modelConfig, modelWeights, 0);

	//输入
        std::cout << "input image or video filename: ";
        if(filename.size() == 0) std::cin >> filename;
        string const file_ext = filename.substr(filename.find_last_of(".") + 1);
        string const protocol = filename.substr(0, 7);
        //如果是图像
        if (file_ext == "jpg")
	{
                Mat frame = imread(filename);
		//Mat图像转为yolo输入格式
		shared_ptr<image_t> detImg = detector.mat_to_image_resize(frame);
		//前向预测
		vector<bbox_t> outs = detector.detect_resized(*detImg, frame.cols, frame.rows, 0.25);
		//画图
		Drawer(frame, outs, classes);
		imwrite("./data/result.jpg", frame);
	}
	//视频
	else
	{
                VideoCapture cap(filename);
                int frames = cap.get(CAP_PROP_FRAME_COUNT);//获取视频针数目(一帧就是一张图片)
                double fps = cap.get(CAP_PROP_FPS);//获取每针视频的频率
                // 获取帧的视频宽度,视频高度
                Size size = Size(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT));
                cout << frames << endl;
                cout << fps << endl;
                cout << size << endl;
                //创建写入对象,需要指定,帧率和视频宽高
                VideoWriter writer;
                writer.open("./data/test.avi", VideoWriter::fourcc('M','J','P','G'), fps, size);
		while (1) 
		{
			Mat frame;
			cap >> frame;
			if (frame.empty()) 
				break;

			//Mat图像转为yolo输入格式
			shared_ptr<image_t> detImg = detector.mat_to_image_resize(frame);
			//前向预测
			vector<bbox_t> outs = detector.detect_resized(*detImg, frame.cols, frame.rows, 0.25);
			//画图
			Drawer(frame, outs, classes);
			writer << frame;
		}
		cap.release();
	}
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 2.8) # 最低版本需求
project(1c++) #项目名
#opencv
add_definitions(-std=c++11) 
ADD_DEFINITIONS(-DOPENCV)
ADD_DEFINITIONS(-DGPU)
#########   opencv   #########
set(OpenCV_DIR "../opencv-4.4.0")
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
#########         darknet   #########
include_directories(/home/ycc/darknet-master/include)
find_library(darknet libdarknet.so /home/ycc/darknet-master)
add_executable(${PROJECT_NAME} "yolov4.cpp" )
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS}  ${darknet})
cmake .
make

生成1c++可执行程序

./1c++

新建data文件夹,输入如下,便可在data下得到保存结果:

test.jpg
vtest.avi
rtsp......

Guess you like

Origin blog.csdn.net/qq_34717531/article/details/108626517