训练 部署 见: https://blog.csdn.net/qq_36758461/article/details/121431614
这是 视频检测 并保存… 小白部署学习记录
整理下 文件 依赖思路 :
yolo-fastestv2.h
只做声明,声明了 TargetBox 和 yoloFastestv2 类, 编译后不产生代码;
yolo-fastestv2.cpp
进行 代码实现
TargetBox 用在 yolo-fastestv2.cpp 中 vector 数据类型中
yoloFastestv2 类封装了 具体的一些函数:
(1) yoloFastestv2::yoloFastestv2() 模型的参数配置
(2) yoloFastestv2::~yoloFastestv2() 退出类
(3) int yoloFastestv2::loadModel() ncnn 模型加载
(4) int yoloFastestv2::detection() 检测 -> 调用 predHandle, nmsHandle
- int yoloFastestv2::nmsHandle() NMS处理
- int yoloFastestv2::predHandle() 特征图后处理 -> 调用 getCategory
- int yoloFastestv2::getCategory() 检测类别分数处理
video_demo.cpp
#include "yolo-fastestv2.h"
int main()
{
static const char* class_names[] = {
"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"
};
// static const char* class_names[] = {
// "airplane", "ship", "storage tank", "baseball diamond", "tennis court",
// "basketball court", "ground track field", "harbor", "bridge", "vehicle"
// };
//在yolo-fastestv2.h 中, 有一个类函数 yoloFastestv2
yoloFastestv2 api;
api.loadModel("./model/yolo-fastestv2-opt.param",
"./model/yolo-fastestv2-opt.bin");
//cv::Mat cvImg = cv::imread("058.jpg");
// Vector容器中存放自定义数据类型,存放目标框的信息(cls,score,x,y,w,h,area), 在 yolo-fastestv2.h 有声明
std::vector<TargetBox> boxes;
cv::VideoCapture capture;
capture.open("../../person.mp4");
//获取当前 视频信息
cv::Size S = cv::Size((int)capture.get(CV_CAP_PROP_FRAME_WIDTH),
(int)capture.get(CV_CAP_PROP_FRAME_HEIGHT));
// -----------保存视频的检测结果--------------
cv:: VideoWriter outputVideo;
outputVideo.open("./out.mp4", CV_FOURCC('P','I','M','1'), 30.0, S, true);
if (!outputVideo.isOpened()) {
std::cout << "fail to open!" << std::endl;
return -1;
}
// ---------------------------------
cv::Mat frame;
while (1) {
capture >> frame;//读入视频的帧
if (frame.empty()) break;
// 检测 图像,结果保存在 boxes
api.detection(frame, boxes);
// 可视化,绘制框
for (int i = 0; i < boxes.size(); i++) {
std::cout<<boxes[i].x1<<" "<<boxes[i].y1<<" "<<boxes[i].x2<<" "<<boxes[i].y2
<<" "<<boxes[i].score<<" "<<boxes[i].cate<<std::endl;
char text[256];
sprintf(text, "%s %.1f%%", class_names[boxes[i].cate], boxes[i].score * 100);
int baseLine = 0;
cv::Size label_size = cv::getTextSize(text, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
int x = boxes[i].x1;
int y = boxes[i].y1 - label_size.height - baseLine;
if (y < 0)
y = 0;
if (x + label_size.width > frame.cols)
x = frame.cols - label_size.width;
cv::rectangle(frame, cv::Rect(cv::Point(x, y), cv::Size(label_size.width, label_size.height + baseLine)),
cv::Scalar(255, 255, 255), -1);
cv::putText(frame, text, cv::Point(x, y + label_size.height),
cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0));
cv::rectangle (frame, cv::Point(boxes[i].x1, boxes[i].y1),
cv::Point(boxes[i].x2, boxes[i].y2), cv::Scalar(255, 255, 0), 2, 2, 0);
}
cv:: namedWindow("img",CV_WINDOW_NORMAL);
cv:: imshow("img", frame);
// 保存 视频检测文件
outputVideo.write(frame); //把图像写入视频流
//按下ESC退出整个程序
int c = cv::waitKey(30);
if( char(c) == 27) return -1;
}
// cv::imwrite("output.png", cvImg);
// 关闭释放
capture.release();
cv::waitKey(0);
return 0;
}