C++ TensorRT yolov8推理 CUDA核函数加速前处理

news2024/11/27 22:37:30

目录

效果

4K视频 CPU前处理效果

4K视频 CUDA核函数前处理效果

2K视频 CUDA核函数前处理效果

1080P 视频 CUDA核函数前处理效果

模型 

电脑环境

项目

代码

下载


效果

C++ TensorRT yolov8推理 CUDA核函数加速前处理

4K视频 CPU前处理效果

4K视频 CUDA核函数前处理效果

2K视频 CUDA核函数前处理效果

1080P 视频 CUDA核函数前处理效果

模型 

Model Properties
-------------------------
date:2023-09-05T13:17:15.396588
description:Ultralytics YOLOv8n model trained on coco.yaml
author:Ultralytics
task:detect
license:AGPL-3.0 https://ultralytics.com/license
version:8.0.170
stride:32
batch:1
imgsz:[640, 640]
names:{0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 4: 'airplane', 5: 'bus', 6: 'train', 7: 'truck', 8: 'boat', 9: 'traffic light', 10: 'fire hydrant', 11: 'stop sign', 12: 'parking meter', 13: 'bench', 14: 'bird', 15: 'cat', 16: 'dog', 17: 'horse', 18: 'sheep', 19: 'cow', 20: 'elephant', 21: 'bear', 22: 'zebra', 23: 'giraffe', 24: 'backpack', 25: 'umbrella', 26: 'handbag', 27: 'tie', 28: 'suitcase', 29: 'frisbee', 30: 'skis', 31: 'snowboard', 32: 'sports ball', 33: 'kite', 34: 'baseball bat', 35: 'baseball glove', 36: 'skateboard', 37: 'surfboard', 38: 'tennis racket', 39: 'bottle', 40: 'wine glass', 41: 'cup', 42: 'fork', 43: 'knife', 44: 'spoon', 45: 'bowl', 46: 'banana', 47: 'apple', 48: 'sandwich', 49: 'orange', 50: 'broccoli', 51: 'carrot', 52: 'hot dog', 53: 'pizza', 54: 'donut', 55: 'cake', 56: 'chair', 57: 'couch', 58: 'potted plant', 59: 'bed', 60: 'dining table', 61: 'toilet', 62: 'tv', 63: 'laptop', 64: 'mouse', 65: 'remote', 66: 'keyboard', 67: 'cell phone', 68: 'microwave', 69: 'oven', 70: 'toaster', 71: 'sink', 72: 'refrigerator', 73: 'book', 74: 'clock', 75: 'vase', 76: 'scissors', 77: 'teddy bear', 78: 'hair drier', 79: 'toothbrush'}
---------------------------------------------------------------

Inputs
-------------------------
name:images
tensor:Float[1, 3, 640, 640]
---------------------------------------------------------------

Outputs
-------------------------
name:output0
tensor:Float[1, 84, 8400]
---------------------------------------------------------------

电脑环境

处理器:AMD Ryzen 7 7735H with Radeon Graphics 3.20 GHz
内存:16.0 GB 
显卡:NVIDIA GeForce RTX 4060 Laptop GPU
操作系统:Windows 10 企业版
opencv-4.8.1
CUDA12.4
TensorRT-8.6.1.6
VS2022

项目

包含目录

库目录

附件依赖项

cublas.lib
cublasLt.lib
cuda.lib
cudadevrt.lib
cudart.lib
cudart_static.lib
cudnn.lib
cudnn64_8.lib
cudnn_adv_infer.lib
cudnn_adv_infer64_8.lib
cudnn_adv_train.lib
cudnn_adv_train64_8.lib
cudnn_cnn_infer.lib
cudnn_cnn_infer64_8.lib
cudnn_cnn_train.lib
cudnn_cnn_train64_8.lib
cudnn_ops_infer.lib
cudnn_ops_infer64_8.lib
cudnn_ops_train.lib
cudnn_ops_train64_8.lib
cufft.lib
cufftw.lib
cufilt.lib
curand.lib
cusolver.lib
cusolverMg.lib
cusparse.lib
nppc.lib
nppial.lib
nppicc.lib
nppidei.lib
nppif.lib
nppig.lib
nppim.lib
nppist.lib
nppisu.lib
nppitc.lib
npps.lib
nvblas.lib
nvJitLink.lib
nvJitLink_static.lib
nvjpeg.lib
nvml.lib
nvptxcompiler_static.lib
nvrtc-builtins_static.lib
nvrtc.lib
nvrtc_static.lib
OpenCL.lib
nvinfer.lib
nvinfer_dispatch.lib
nvinfer_lean.lib
nvinfer_plugin.lib
nvinfer_vc_plugin.lib
nvonnxparser.lib
nvparsers.lib
opencv_world481.lib

代码

#define _CRT_SECURE_NO_DEPRECATE

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <fstream>
#include <numeric>
#include "NvInfer.h"
#include "kernel_function.h"
#include "utils.h"

std::vector<std::string> labels;
float score_threshold = 0.3f;
float nms_threshold = 0.5f;
std::string lable_path = "";
std::string engin_path = "";
std::string video_path = "";

utils::NvinferStruct* p = nullptr;
utils::Logger logger;

utils::InitParameter m_param;
utils::AffineMat m_dst2src;

int src_w = 0;
int src_h = 0;
int dst_w = 640;
int dst_h = 640;
double fps = 0;
int output_size = 0;

double preprocessTime = 0;
double inferTime = 0;
double postprocessTime = 0;
double totalTime = 0;
double detFps = 0;

// input
unsigned char* m_input_src_device = nullptr;
float* m_input_resize_device = nullptr;
float* m_input_rgb_device = nullptr;
float* m_input_norm_device = nullptr;
float* m_input_hwc_device = nullptr;
// output
float* m_output_src_device = nullptr;
float* output_data = nullptr;

//初始化
int init() {

    std::ifstream lable_file(lable_path);
    if (!lable_file.is_open())
    {
        std::cerr << "Error opening file: " << lable_path << std::endl;
        return -1;
    }
    std::string line;
    while (std::getline(lable_file, line))
    {
        if (!line.empty())
        {
            labels.push_back(line);
        }
    }
    lable_file.close();

    // 以二进制方式读取文件
    std::ifstream engin_file(engin_path.data(), std::ios::binary);
    if (!engin_file.good()) {
        std::cerr << "文件无法打开,请确定文件是否可用!" << std::endl;
        return -1;
    }
    size_t size = 0;
    engin_file.seekg(0, engin_file.end);    // 将读指针从文件末尾开始移动0个字节
    size = engin_file.tellg();    // 返回读指针的位置,此时读指针的位置就是文件的字节数
    engin_file.seekg(0, engin_file.beg);    // 将读指针从文件开头开始移动0个字节
    char* modelStream = new char[size];
    engin_file.read(modelStream, size);
    engin_file.close();// 关闭文件

    //创建推理核心结构体,初始化变量
    p = new utils::NvinferStruct();

    //初始化反序列化引擎
    p->runtime = nvinfer1::createInferRuntime(logger);

    // 初始化推理引擎
    p->engine = p->runtime->deserializeCudaEngine(modelStream, size);

    // 创建上下文
    p->context = p->engine->createExecutionContext();
    int numNode = p->engine->getNbBindings();

    delete[] modelStream;

    output_size = 1 * (labels.size() + 4) * 8400;;
    output_data = new float[output_size];

    float a = float(dst_h) / src_h;
    float b = float(dst_w) / src_w;
    float scale = a < b ? a : b;

    /*cv::Mat src2dst = (cv::Mat_<float>(2, 3) << scale, 0.f, (-scale * src_w + dst_w + scale - 1) * 0.5,
        0.f, scale, (-scale * src_h + dst_h + scale - 1) * 0.5);*/

    cv::Mat src2dst = (cv::Mat_<float>(2, 3) << scale, 0.f, (-scale * src_w + dst_w) * 0.5,
        0.f, scale, (-scale * src_h + dst_h) * 0.5);

    cv::Mat dst2src = cv::Mat::zeros(2, 3, CV_32FC1);

    cv::invertAffineTransform(src2dst, dst2src);

    m_dst2src.v0 = dst2src.ptr<float>(0)[0];
    m_dst2src.v1 = dst2src.ptr<float>(0)[1];
    m_dst2src.v2 = dst2src.ptr<float>(0)[2];
    m_dst2src.v3 = dst2src.ptr<float>(1)[0];
    m_dst2src.v4 = dst2src.ptr<float>(1)[1];
    m_dst2src.v5 = dst2src.ptr<float>(1)[2];

    CHECK(cudaMalloc(&m_input_src_device, 1 * 3 * src_h * src_w * sizeof(unsigned char)));
    CHECK(cudaMalloc(&m_input_resize_device, 1 * 3 * dst_h * dst_w * sizeof(float)));
    CHECK(cudaMalloc(&m_input_rgb_device, 1 * 3 * dst_h * dst_w * sizeof(float)));
    CHECK(cudaMalloc(&m_input_norm_device, 1 * 3 * dst_h * dst_w * sizeof(float)));
    CHECK(cudaMalloc(&m_input_hwc_device, 1 * 3 * dst_h * dst_w * sizeof(float)));
    CHECK(cudaMalloc(&m_output_src_device, 1 * output_size * sizeof(float)));

    return 0;
}

//前处理
void preprocess(cv::Mat& frame) {

    CHECK(cudaMemcpy(m_input_src_device, frame.data, sizeof(unsigned char) * 3 * src_h * src_w, cudaMemcpyHostToDevice));

    resizeDevice(1, m_input_src_device, src_w, src_h, m_input_resize_device, dst_w, dst_h, 114, m_dst2src);

    bgr2rgbDevice(1, m_input_resize_device, dst_w, dst_h, m_input_rgb_device, dst_w, dst_h);

    normDevice(1, m_input_rgb_device, dst_w, dst_h, m_input_norm_device, dst_w, dst_h, m_param);

    hwc2chwDevice(1, m_input_norm_device, dst_w, dst_h, m_input_hwc_device, dst_w, dst_h);
}

//后处理
void postprocess(std::vector<utils::detresult>& detectionResult) {

    CHECK(cudaMemcpy(output_data, m_output_src_device, output_size * sizeof(float), cudaMemcpyDeviceToHost));

    cv::Mat dout(labels.size() + 4, 8400, CV_32F, output_data);
    cv::Mat det_output = dout.t();

    std::vector<cv::Rect> boxes;
    std::vector<int> classIds;
    std::vector<float> confidences;

    const float ratio_h = dst_h / (float)src_h;
    const float ratio_w = dst_w / (float)src_w;

    for (int i = 0; i < det_output.rows; i++)
    {
        cv::Mat classes_scores = det_output.row(i).colRange(4, labels.size() + 4);
        cv::Point classIdPoint;
        double score;
        cv::minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);

        if (score > score_threshold)
        {
            float cx = det_output.at<float>(i, 0);
            float cy = det_output.at<float>(i, 1);
            float ow = det_output.at<float>(i, 2);
            float oh = det_output.at<float>(i, 3);

            int x = static_cast<int>((cx - 0.5 * ow));
            int y = static_cast<int>((cy - 0.5 * oh));

            int width = static_cast<int>(ow);
            int height = static_cast<int>(oh);
            // 基于纵横比调整边界框坐标
            if (ratio_h > ratio_w)
            {
                x = x / ratio_w;
                y = (y - (dst_h - ratio_w * src_h) / 2) / ratio_w;
                width = width / ratio_w;
                height = height / ratio_w;
            }
            else
            {
                x = (x - (dst_w - ratio_h * src_w) / 2) / ratio_h;
                y = y / ratio_h;
                width = width / ratio_h;
                height = height / ratio_h;
            }

            // 坐标值安全校验
            x = std::max(x, 0);
            y = std::max(y, 0);
            width = std::min(width, src_w - x);
            height = std::min(height, src_h - y);

            cv::Rect box;
            box.x = x;
            box.y = y;
            box.width = width;
            box.height = height;

            boxes.push_back(box);
            classIds.push_back(classIdPoint.x);
            confidences.push_back(score);
        }
    }

    std::vector<int> indexes;
    cv::dnn::NMSBoxes(boxes, confidences, score_threshold, nms_threshold, indexes);

    for (size_t i = 0; i < indexes.size(); i++)
    {
        int index = indexes[i];
        utils::detresult box(labels[classIds[index]], classIds[index], confidences[index], boxes[index]);
        detectionResult.push_back(box);
    }

}

//绘制
void draw(cv::Mat& frame, std::vector<utils::detresult>& detectionResult) {

    for (size_t i = 0; i < detectionResult.size(); ++i)
    {
        utils::detresult box = detectionResult[i];
        cv::rectangle(frame, box.rect, cv::Scalar(0, 0, 255), 2);
        std::string label = box.className + ":" + cv::format("%.2f", box.confidence);
        putText(frame, label, cv::Point(box.rect.x, box.rect.y - 5), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
    }

    // 绘制时间
    putText(frame, "preprocessTime:" + std::to_string(preprocessTime * 1000) + "ms", cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
    putText(frame, "inferTime:" + std::to_string(inferTime * 1000) + "ms", cv::Point(10, 70), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
    putText(frame, "postprocessTime:" + std::to_string(postprocessTime * 1000) + "ms", cv::Point(10, 110), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
    putText(frame, "totalTime:" + std::to_string(totalTime * 1000) + "ms", cv::Point(10, 150), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
    putText(frame, "detFps:" + std::to_string(detFps), cv::Point(10, 190), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);

    cv::imshow("detresult", frame);

}

//清理
void destroy() {

    p->context->destroy();
    p->engine->destroy();
    p->runtime->destroy();
    delete p;

    // input
    CHECK(cudaFree(m_input_src_device));
    CHECK(cudaFree(m_input_resize_device));
    CHECK(cudaFree(m_input_rgb_device));
    CHECK(cudaFree(m_input_norm_device));
    CHECK(cudaFree(m_input_hwc_device));
    // output
    CHECK(cudaFree(m_output_src_device));
    delete output_data;
}

int main()
{
    lable_path = "model/lable.txt";
    engin_path = "model/yolov8n.engine";
    video_path = "test/VID_4K.mp4"; //3840x2160

    cv::VideoCapture capture(video_path);
    // 检查视频是否成功打开
    if (!capture.isOpened())
    {
        std::cout << "无法读取视频文件" << std::endl;
        return -1;
    }

    fps = capture.get(cv::CAP_PROP_FPS);
    src_w = static_cast<int>(capture.get(cv::CAP_PROP_FRAME_WIDTH));
    src_h = static_cast<int>(capture.get(cv::CAP_PROP_FRAME_HEIGHT));
    dst_w = 640;
    dst_h = 640;
    score_threshold = 0.3f;
    nms_threshold = 0.5f;

    //初始化
    init();

    cv::Mat frame;
    while (true)
    {
        bool success = capture.read(frame); // 读取一帧数据
        // 检查是否成功读取帧
        if (!success)
        {
            std::cout << "读取完毕" << std::endl;
            break;
        }

        //前处理
        double start = (double)cv::getTickCount();
        preprocess(frame);
        preprocessTime = ((double)cv::getTickCount() - start) / cv::getTickFrequency();

        //推理
        start = (double)cv::getTickCount();
        float* bindings[] = { m_input_hwc_device, m_output_src_device };
        bool context = p->context->executeV2((void**)bindings);
        inferTime = ((double)cv::getTickCount() - start) / cv::getTickFrequency();

        //后处理
        start = (double)cv::getTickCount();
        std::vector<utils::detresult> detectionResult;
        postprocess(detectionResult);
        postprocessTime = ((double)cv::getTickCount() - start) / cv::getTickFrequency();

        //总时间
        totalTime = preprocessTime + inferTime + postprocessTime;
        detFps = (1 / (totalTime));

        //绘制、显示
        cv::namedWindow("detresult", cv::WINDOW_NORMAL); // cv::WINDOW_NORMAL允许用户调整窗口大小
        //cv::resizeWindow("detresult", src_w / 2, src_h / 2); // 设置窗口的宽度和高度
        draw(frame, detectionResult);

        if (cv::waitKey(1) == 27) // 通过按下ESC键退出循环
        {
            break;
        }
    }

    cv::destroyAllWindows();

    destroy();

    return 0;
}

#define _CRT_SECURE_NO_DEPRECATE

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <fstream>
#include <numeric>
#include "NvInfer.h"
#include "kernel_function.h"
#include "utils.h"

std::vector<std::string> labels;
float score_threshold = 0.3f;
float nms_threshold = 0.5f;
std::string lable_path = "";
std::string engin_path = "";
std::string video_path = "";

utils::NvinferStruct* p = nullptr;
utils::Logger logger;

utils::InitParameter m_param;
utils::AffineMat m_dst2src;

int src_w = 0;
int src_h = 0;
int dst_w = 640;
int dst_h = 640;
double fps = 0;
int output_size = 0;

double preprocessTime = 0;
double inferTime = 0;
double postprocessTime = 0;
double totalTime = 0;
double detFps = 0;

// input
unsigned char* m_input_src_device = nullptr;
float* m_input_resize_device = nullptr;
float* m_input_rgb_device = nullptr;
float* m_input_norm_device = nullptr;
float* m_input_hwc_device = nullptr;
// output
float* m_output_src_device = nullptr;
float* output_data = nullptr;

//初始化
int init() {

	std::ifstream lable_file(lable_path);
	if (!lable_file.is_open())
	{
		std::cerr << "Error opening file: " << lable_path << std::endl;
		return -1;
	}
	std::string line;
	while (std::getline(lable_file, line))
	{
		if (!line.empty())
		{
			labels.push_back(line);
		}
	}
	lable_file.close();

	// 以二进制方式读取文件
	std::ifstream engin_file(engin_path.data(), std::ios::binary);
	if (!engin_file.good()) {
		std::cerr << "文件无法打开,请确定文件是否可用!" << std::endl;
		return -1;
	}
	size_t size = 0;
	engin_file.seekg(0, engin_file.end);	// 将读指针从文件末尾开始移动0个字节
	size = engin_file.tellg();	// 返回读指针的位置,此时读指针的位置就是文件的字节数
	engin_file.seekg(0, engin_file.beg);	// 将读指针从文件开头开始移动0个字节
	char* modelStream = new char[size];
	engin_file.read(modelStream, size);
	engin_file.close();// 关闭文件

	//创建推理核心结构体,初始化变量
	p = new utils::NvinferStruct();

	//初始化反序列化引擎
	p->runtime = nvinfer1::createInferRuntime(logger);

	// 初始化推理引擎
	p->engine = p->runtime->deserializeCudaEngine(modelStream, size);

	// 创建上下文
	p->context = p->engine->createExecutionContext();
	int numNode = p->engine->getNbBindings();

	delete[] modelStream;

	output_size = 1 * (labels.size() + 4) * 8400;;
	output_data = new float[output_size];

	float a = float(dst_h) / src_h;
	float b = float(dst_w) / src_w;
	float scale = a < b ? a : b;

	/*cv::Mat src2dst = (cv::Mat_<float>(2, 3) << scale, 0.f, (-scale * src_w + dst_w + scale - 1) * 0.5,
		0.f, scale, (-scale * src_h + dst_h + scale - 1) * 0.5);*/

	cv::Mat src2dst = (cv::Mat_<float>(2, 3) << scale, 0.f, (-scale * src_w + dst_w) * 0.5,
		0.f, scale, (-scale * src_h + dst_h) * 0.5);

	cv::Mat dst2src = cv::Mat::zeros(2, 3, CV_32FC1);

	cv::invertAffineTransform(src2dst, dst2src);

	m_dst2src.v0 = dst2src.ptr<float>(0)[0];
	m_dst2src.v1 = dst2src.ptr<float>(0)[1];
	m_dst2src.v2 = dst2src.ptr<float>(0)[2];
	m_dst2src.v3 = dst2src.ptr<float>(1)[0];
	m_dst2src.v4 = dst2src.ptr<float>(1)[1];
	m_dst2src.v5 = dst2src.ptr<float>(1)[2];

	CHECK(cudaMalloc(&m_input_src_device, 1 * 3 * src_h * src_w * sizeof(unsigned char)));
	CHECK(cudaMalloc(&m_input_resize_device, 1 * 3 * dst_h * dst_w * sizeof(float)));
	CHECK(cudaMalloc(&m_input_rgb_device, 1 * 3 * dst_h * dst_w * sizeof(float)));
	CHECK(cudaMalloc(&m_input_norm_device, 1 * 3 * dst_h * dst_w * sizeof(float)));
	CHECK(cudaMalloc(&m_input_hwc_device, 1 * 3 * dst_h * dst_w * sizeof(float)));
	CHECK(cudaMalloc(&m_output_src_device, 1 * output_size * sizeof(float)));

	return 0;
}

//前处理
void preprocess(cv::Mat& frame) {

	CHECK(cudaMemcpy(m_input_src_device, frame.data, sizeof(unsigned char) * 3 * src_h * src_w, cudaMemcpyHostToDevice));

	resizeDevice(1, m_input_src_device, src_w, src_h, m_input_resize_device, dst_w, dst_h, 114, m_dst2src);

	bgr2rgbDevice(1, m_input_resize_device, dst_w, dst_h, m_input_rgb_device, dst_w, dst_h);

	normDevice(1, m_input_rgb_device, dst_w, dst_h, m_input_norm_device, dst_w, dst_h, m_param);

	hwc2chwDevice(1, m_input_norm_device, dst_w, dst_h, m_input_hwc_device, dst_w, dst_h);
}

//后处理
void postprocess(std::vector<utils::detresult>& detectionResult) {

	CHECK(cudaMemcpy(output_data, m_output_src_device, output_size * sizeof(float), cudaMemcpyDeviceToHost));

	cv::Mat dout(labels.size() + 4, 8400, CV_32F, output_data);
	cv::Mat det_output = dout.t();

	std::vector<cv::Rect> boxes;
	std::vector<int> classIds;
	std::vector<float> confidences;

	const float ratio_h = dst_h / (float)src_h;
	const float ratio_w = dst_w / (float)src_w;

	for (int i = 0; i < det_output.rows; i++)
	{
		cv::Mat classes_scores = det_output.row(i).colRange(4, labels.size() + 4);
		cv::Point classIdPoint;
		double score;
		cv::minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint);

		if (score > score_threshold)
		{
			float cx = det_output.at<float>(i, 0);
			float cy = det_output.at<float>(i, 1);
			float ow = det_output.at<float>(i, 2);
			float oh = det_output.at<float>(i, 3);

			int x = static_cast<int>((cx - 0.5 * ow));
			int y = static_cast<int>((cy - 0.5 * oh));

			int width = static_cast<int>(ow);
			int height = static_cast<int>(oh);
			// 基于纵横比调整边界框坐标
			if (ratio_h > ratio_w)
			{
				x = x / ratio_w;
				y = (y - (dst_h - ratio_w * src_h) / 2) / ratio_w;
				width = width / ratio_w;
				height = height / ratio_w;
			}
			else
			{
				x = (x - (dst_w - ratio_h * src_w) / 2) / ratio_h;
				y = y / ratio_h;
				width = width / ratio_h;
				height = height / ratio_h;
			}

			// 坐标值安全校验
			x = std::max(x, 0);
			y = std::max(y, 0);
			width = std::min(width, src_w - x);
			height = std::min(height, src_h - y);

			cv::Rect box;
			box.x = x;
			box.y = y;
			box.width = width;
			box.height = height;

			boxes.push_back(box);
			classIds.push_back(classIdPoint.x);
			confidences.push_back(score);
		}
	}

	std::vector<int> indexes;
	cv::dnn::NMSBoxes(boxes, confidences, score_threshold, nms_threshold, indexes);

	for (size_t i = 0; i < indexes.size(); i++)
	{
		int index = indexes[i];
		utils::detresult box(labels[classIds[index]], classIds[index], confidences[index], boxes[index]);
		detectionResult.push_back(box);
	}

}

//绘制
void draw(cv::Mat& frame, std::vector<utils::detresult>& detectionResult) {

	for (size_t i = 0; i < detectionResult.size(); ++i)
	{
		utils::detresult box = detectionResult[i];
		cv::rectangle(frame, box.rect, cv::Scalar(0, 0, 255), 2);
		std::string label = box.className + ":" + cv::format("%.2f", box.confidence);
		putText(frame, label, cv::Point(box.rect.x, box.rect.y - 5), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
	}

	// 绘制时间
	putText(frame, "preprocessTime:" + std::to_string(preprocessTime * 1000) + "ms", cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
	putText(frame, "inferTime:" + std::to_string(inferTime * 1000) + "ms", cv::Point(10, 70), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
	putText(frame, "postprocessTime:" + std::to_string(postprocessTime * 1000) + "ms", cv::Point(10, 110), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
	putText(frame, "totalTime:" + std::to_string(totalTime * 1000) + "ms", cv::Point(10, 150), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);
	putText(frame, "detFps:" + std::to_string(detFps), cv::Point(10, 190), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(0, 255, 0), 2);

	cv::imshow("detresult", frame);

}

//清理
void destroy() {

	p->context->destroy();
	p->engine->destroy();
	p->runtime->destroy();
	delete p;

	// input
	CHECK(cudaFree(m_input_src_device));
	CHECK(cudaFree(m_input_resize_device));
	CHECK(cudaFree(m_input_rgb_device));
	CHECK(cudaFree(m_input_norm_device));
	CHECK(cudaFree(m_input_hwc_device));
	// output
	CHECK(cudaFree(m_output_src_device));
	delete output_data;
}

int main()
{
	lable_path = "model/lable.txt";
	engin_path = "model/yolov8n.engine";
	video_path = "test/VID_4K.mp4"; //3840x2160

	cv::VideoCapture capture(video_path);
	// 检查视频是否成功打开
	if (!capture.isOpened())
	{
		std::cout << "无法读取视频文件" << std::endl;
		return -1;
	}

	fps = capture.get(cv::CAP_PROP_FPS);
	src_w = static_cast<int>(capture.get(cv::CAP_PROP_FRAME_WIDTH));
	src_h = static_cast<int>(capture.get(cv::CAP_PROP_FRAME_HEIGHT));
	dst_w = 640;
	dst_h = 640;
	score_threshold = 0.3f;
	nms_threshold = 0.5f;

	//初始化
	init();

	cv::Mat frame;
	while (true)
	{
		bool success = capture.read(frame); // 读取一帧数据
		// 检查是否成功读取帧
		if (!success)
		{
			std::cout << "读取完毕" << std::endl;
			break;
		}

		//前处理
		double start = (double)cv::getTickCount();
		preprocess(frame);
		preprocessTime = ((double)cv::getTickCount() - start) / cv::getTickFrequency();

		//推理
		start = (double)cv::getTickCount();
		float* bindings[] = { m_input_hwc_device, m_output_src_device };
		bool context = p->context->executeV2((void**)bindings);
		inferTime = ((double)cv::getTickCount() - start) / cv::getTickFrequency();

		//后处理
		start = (double)cv::getTickCount();
		std::vector<utils::detresult> detectionResult;
		postprocess(detectionResult);
		postprocessTime = ((double)cv::getTickCount() - start) / cv::getTickFrequency();

		//总时间
		totalTime = preprocessTime + inferTime + postprocessTime;
		detFps = (1 / (totalTime));

		//绘制、显示
		cv::namedWindow("detresult", cv::WINDOW_NORMAL); // cv::WINDOW_NORMAL允许用户调整窗口大小
		//cv::resizeWindow("detresult", src_w / 2, src_h / 2); // 设置窗口的宽度和高度
		draw(frame, detectionResult);

		if (cv::waitKey(1) == 27) // 通过按下ESC键退出循环
		{
			break;
		}
	}

	cv::destroyAllWindows();

	destroy();

	return 0;
}

下载

源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2227796.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动化测试覆盖率提升的关键步骤

自动化测试覆盖不足的问题可以通过增加测试用例的数量和质量、引入代码覆盖率分析工具、加强团队的测试意识和技能、优化测试框架和工具、自动化测试与手动测试相结合等方式来解决。其中&#xff0c;引入代码覆盖率分析工具是关键&#xff0c;它可以帮助我们精准地识别未被测试…

STM32-Cube定时器TIM

一、内部时钟源 1、创建项目 File → New → STM32 project选择STM32F103C8T6单片机&#xff0c;命名TIM 2、配置单片机 1.打开USART1&#xff0c;方便我们与电脑连接查看数据 开启UART1并开启中断。 2、设置时钟源 开启外部高速晶振 将时钟频率设置为72MHz 设置调试模…

TCP全连接队列与 tcpdump 抓包

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;计算机网络高效通关之路 欢迎大家点赞收藏评论&#x1f60a; 目录 listen第二个参数详解 全连接队列与半连接队列半开放连接队列&#xff08;SYN队列&#xff09;全连接队列&#xff08;接受队列…

构建灵活、高效的HTTP/1.1应用:探索h11库

文章目录 构建灵活、高效的HTTP/1.1应用&#xff1a;探索h11库背景这个库是什么&#xff1f;如何安装这个库&#xff1f;库函数使用方法使用场景常见的Bug及解决方案总结 构建灵活、高效的HTTP/1.1应用&#xff1a;探索h11库 背景 在现代网络应用中&#xff0c;HTTP协议是基础…

Linux 安装MySQL(Cenots版本)

在Linux下安装mysql有很多方法&#xff0c;比如说&#xff1a; 压缩包解压&#xff08;一般为tar.gz&#xff09; 编译好的安装包&#xff08;RPM、DPKG等&#xff09; 在线安装&#xff08;YUM、APT等&#xff09; 在centos环境中&#xff0c;我们一般都用yum源安装。 一 删除…

2. Flink快速上手

文章目录 1. 环境准备1.1 系统环境1.2 安装配置Java 8和Scala 2.121.3 使用集成开发环境IntelliJ IDEA1.4 安装插件2. 创建项目2.1 创建工程2.1.1 创建Maven项目2.1.2 设置项目基本信息2.1.3 生成项目基本框架2.2 添加项目依赖2.2.1 添加Flink相关依赖2.2.2 刷新项目依赖3. 编写…

Docker使用-在Maven里面配置阿里云容器镜像仓库

准备环境 1.安装Dockerdesktop 参考文章&#xff1a;Docker Desktop安装 2.Windows 环境 3.IdeaMaven 4.阿里云容器镜像仓库.阿里云容器镜像仓库 5.SpringBoot 例子 通过网盘分享的文件&#xff1a;springboot-docker-demo.zip 链接: https://pan.baidu.com/s/1MD0uI1HG9SjYv…

群控系统服务端开发模式-应用开发-业务架构逻辑开发Redis封装

Redis是现代互联网开发世界不可缺少的一部分&#xff0c;比如登录token过期时间、系统配置等场所必用。 一、安装Redis扩展 composer require predis/predis 二、设置Redis参数 在根目录下config文件夹中找到cache.php文件&#xff0c;然后在stores数组下追加redis配置&#…

【机器学习】揭秘XGboost:高效梯度提升算法的实践与应用

目录 &#x1f354; XGBoost 原理 1.1 目标函数确定和树的复杂度介绍 1.2 XGBoost目标函数的推导 1.3 泰勒公式展开 1.4 化简目标函数 1.5 问题再次转换 1.6 对叶子结点求导 1.7 XGBoost的回归树构建方法 &#x1f354; XGBoost API 2.1 通用参数 2.2 Booster 参数 …

太速科技-430-基于RFSOC的8路5G ADC和8路10G的DAC PCIe卡

430-基于RFSOC的8路5G ADC和8路10G的DAC PCIe卡 一、板卡概述 板卡使用Xilinx的第三代RFSOC系列&#xff0c;单颗芯片包含8路ADC和DAC&#xff0c;64-bit Cortex A53系列4核CPU&#xff0c;Cortex-R5F实时处理核&#xff0c;以及大容量FPGA。 对主机接口采用PCIe Gen3x…

SpringBoot篇(运维实用篇 - 临时属性)

目录 一、临时属性设置 1. 简介 2. 属性加载优先级 那是否还有其他的配置方式呢&#xff1f; 3. 知识小结 二、开发环境中使用临时属性 1. 如何操作 2. 知识小结 3. 思考 三、配置文件分类 1. 简介 2. 4个级别 3. 为什么设计多种配置文件&#xff1f; 一个典型的应…

基于SSM+微信小程序的汽车维修管理系统(汽车5)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 基于SSM微信小程序的汽车维修管理系统实现了三个角色&#xff1a;管理员、员工、用户。 1、管理员实现了首页、管理员管理员、员工管理、用户管理、车辆信息管理、配件管理等 2、员工实…

【51 Pandas+Pyecharts | 深圳市共享单车数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 处理起始时间、结束时间2.4 增加骑行时长区间列2.5 增加骑行里程区间列 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 各…

海亮科技亮相第84届中国教装展 尽显生于校园 长于校园教育基因

10月25日&#xff0c;第84届中国教育装备展示会&#xff08;以下简称“教装展”&#xff09;在昆明滇池国际会展中心开幕。作为国内教育装备领域规模最大、影响最广的专业展会&#xff0c;本届教装展以“数字赋能教育&#xff0c;创新引领未来”为主题&#xff0c;为教育领域新…

Mac 电脑 使用sudo创建项目后,给了读写权限,仍报权限问题

问题&#xff1a;sudo创建的项目&#xff0c;都已经改成读写权限了&#xff0c;但是修改项目中的内容还是报没权限。 原因&#xff1a;当你使用 sudo 创建项目时。这是因为 sudo 会以 root 用户的身份创建文件和目录&#xff0c;这些文件和目录默认属于 root 用户&#xff0c;…

vue封装信号强度

图标下载链接: https://pan.baidu.com/s/1828AidkCKU1KTkw1SvBwQg?pwd4k7n 共五格信号 信号5为绿色&#xff0c;信号4为绿色&#xff0c;信号3为黄色&#xff0c;信号2为黄色&#xff0c;信号1为红色&#xff0c;信号0为灰色。 子组件 /components/SignalStrength/index.vu…

【JavaScript】入门详解

JavaScript 作为 Web 开发的基石&#xff0c;赋予了网页动态交互的能力。本文将深入浅出地讲解 JavaScript 的核心概念&#xff0c;并结合最新用法进行详细解释和示例。 1. JavaScript 简介 JavaScript 是一种解释型脚本语言&#xff0c;也称弱类型语言&#xff0c;最初设计用…

标准正态分布的数据 tensorflow 实现正态分布图,python 编程,数据分析和人工智能...

登录后复制 import tensorflow as tfimport matplotlib.pyplot as plt# 设置随机种子以获得可重复的结果tf.random.set_seed(42)# 生成正态分布的数据# mean0 和 stddev1 表示生成标准正态分布的数据# shape(1000,) 表示生成1000个数据点data tf.random.normal(mean0, stddev1…

Web3 与人工智能的跨界合作:重塑数字经济的新引擎

在当今数字化浪潮汹涌澎湃的时代&#xff0c;Web3 和人工智能这两大前沿技术的跨界合作正逐渐成为重塑数字经济的强大新引擎。 Web3 代表着互联网的新一代发展方向&#xff0c;强调去中心化的理念、用户主权以及数据隐私保护。它致力于打破传统互联网由少数巨头掌控的格局&…

【问题记录】当机器人存在多个串口需要绑定时udevadm的作用

一、正常绑定 输入sudo udevadm info -a /dev/ttyUSBx | grep KERNELS 命令 会出现KERNELS的编号&#xff0c;记录编号。 修改规则文件/etc/udev/rules.d/99-usb.rules 添加以下命令 KERNEL"ttyUSB*", KERNELS"2-1.2:1.0", MODE:"0666", GROU…