前篇: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......