有多少人工,就有多少智能

模型部署 - YoloV5模型与TensorRT结合使用的完整流程 - 从模型训练到模型部署 - 人脸检测任务

将YOLOv5与TensorRT结合使用可以显著提高推理速度, 特别是在NVIDIA GPU上。 下面是一个基本的步骤指南, 帮助你了解YOLOv5与TensorRT结合使用的步骤。

人脸检测是一种常见的计算机视觉任务, 下面将详细介绍从模型训练到模型部署的完整流程, 包括使用YOLOv5进行人脸检测的示例, 最后给出C++示例代码。

主要流程包括:

   1. 数据准备

   2. 模型训练

   3. 模型导出为ONNX格式

   4. 模型转换为TensorRT引擎

   5. C++部署示例

 

1. 数据准备

    准备一个包含人脸图像和相应标注的数据集,常用的数据集包括WIDER FACE等。标注格式可以是YOLO格式或者COCO格式。 

2. 模型训练

   使用YOLOv5进行模型训练。 假设已经安装了YOLOv5的依赖。

# 克隆 YOLOv5 仓库
git clone https://github.com/ultralytics/yolov5
cd yolov5

# 安装必要的依赖
pip install -r requirements.txt

创建一个自定义的配置文件 data/faces.yaml,内容如下:

train: /path/to/train/images
val: /path/to/val/images

nc: 1
names: ['face']

然后开始训练:

python train.py --img 640 --batch 16 --epochs 100 --data data/face.yaml --weights yolov5s.pt --cache

 

3. 模型导出为ONNX格式

训练完成后, 将模型导出为ONNX格式:

python export.py --weights runs/train/exp/weights/best.pt --img 640 --batch 1 --device 0 --include onnx

4. 模型转换为TrensorRT引擎

使用TensorRT工具将ONNX模型转换为TensorRT引擎:

/usr/src/tensorrt/bin/trtexec --onnx=best.onnx --saveEngine=best.trt --fp16

5. C++部署示例

以下是一个完整的C++示例代码, 展示如何加载TensorRT引擎进行推理。

必备条件:

确保你已经安装了以下工具和库:

  •    TensorRT
  •    CUDA 
  •    OpenCV

C++ 示例代码

#include <iostream>
#include <fstream>
#include <vector>
#include <NvInfer.h>
#include <NvInferRuntime.h>
#include <cuda_runtime_api.h>
#include <opencv2/opencv.hpp>

using namespace nvinfer1;

class Logger: public ILogger
{
   public:
      void log(Serverity severity, const char* msg) noexcept override
      {
           if(severity != Severity::kINFO)
                std::cout << msg << std::endl;
  
      }     
};

void * safeCudaMalloc(size_t memsize)
{
    void deviceMem;
    cudaError_t stats = cudaMalloc(&deviceMem, memSize);
    if(status != cudaSuccess)
    {
        std::cerr << "cudaMalloc Failed!" << std::endl;
        return nullptr;
    }  
    return deviceMem;
}

bool readEngineFile(const std::string& engineFile, IRuntime*& runtime, ICudaEngine*& engine)
{
        std::ifstream file(engineFile, std::ios::binary);
    if (!file)
    {
        std::cerr << "Failed to open engine file: " << engineFile << std::endl;
        return false;
    }

    file.seekg(0, file.end);
    size_t size = file.tellg();
    file.seekg(0, file.beg);

    std::vector<char> buffer(size);
    file.read(buffer.data(), size);
    file.close();
    
    Logger logger;
    runtime = createInferRuntime(logger);
    if (!runtime)
    {
        std::cerr << "Failed to create TensorRT runtime" << std::endl;
        return false;
    }

    engine = runtime->deserializeCudaEngine(buffer.data(), size);
    if (!engine)
    {
        std::cerr << "Failed to deserialize CUDA engine" << std::endl;
        return false;
    }

    return true;
        
}

void doInference(IExecutionContext& context, float* input, float* output, int batchSize, int inputSize, int outputSize)
{
    const ICudaEngine& engine = context.getEngine();
    assert(engine.getNbBindings() == 2);

    // Allocate GPU buffers
    void* buffers[2];
    const int inputIndex = engine.getBindingIndex("images");
    const int outputIndex = engine.getBindingIndex("output");
    buffers[inputIndex] = safeCudaMalloc(inputSize * batchSize * sizeof(float));
    buffers[outputIndex] = safeCudaMalloc(outputSize * batchSize * sizeof(float));

    // Create stream
    cudaStream_t stream;
    cudaStreamCreate(&stream);

    // Copy input data to GPU
    cudaMemcpyAsync(buffers[inputIndex], input, inputSize * batchSize * sizeof(float), cudaMemcpyHostToDevice, stream);

    // Execute inference
    context.enqueue(batchSize, buffers, stream, nullptr);

    // Copy output data to CPU
    cudaMemcpyAsync(output, buffers[outputIndex], outputSize * batchSize * sizeof(float), cudaMemcpyDeviceToHost, stream);
    cudaStreamSynchronize(stream);

    // Release stream and buffers
    cudaStreamDestroy(stream);
    cudaFree(buffers[inputIndex]);
    cudaFree(buffers[outputIndex]);
}

int main()
{
    const std::string engineFile = "best.trt";
    IRuntime* runtime = nullptr;
    ICudaEngine* engine = nullptr;

    if (!readEngineFile(engineFile, runtime, engine))
    {
        return -1;
    }

    IExecutionContext* context = engine->createExecutionContext();
    if (!context)
    {
        std::cerr << "Failed to create execution context" << std::endl;
        return -1;
    }

    // Load an image using OpenCV
    cv::Mat img = cv::imread("face.jpg");
    cv::resize(img, img, cv::Size(640, 640));
    img.convertTo(img, CV_32FC3, 1.0 / 255);

    // Prepare input data
    std::vector<float> input(3 * 640 * 640);
    std::memcpy(input.data(), img.data, input.size() * sizeof(float));

    // Prepare output data
    const int outputSize = 25200 * 85; // Adjust based on your model's output
    std::vector<float> output(outputSize);

    // Run inference
    doInference(*context, input.data(), output.data(), 1, 3 * 640 * 640, outputSize);

    // Process output data (this is just an example, you'd need to parse and use the output appropriately)
    for (int i = 0; i < outputSize; i += 85)
    {
        float confidence = output[i + 4];
        if (confidence > 0.5)
        {
            std::cout << "Detection: " << i / 85 << " Confidence: " << confidence << std::endl;
        }
    }

    // Clean up
    context->destroy();
    engine->destroy();
    runtime->destroy();
    return 0;
}

Logger 类:自定义的日志记录器,用于捕捉 TensorRT 的日志。
safeCudaMalloc:一个简单的 CUDA 内存分配函数。
readEngineFile:从文件中读取 TensorRT 引擎并反序列化。
doInference:执行推理函数,包括内存分配、数据传输和推理执行。
main 函数:加载 TensorRT 引擎,准备输入数据,执行推理,并处理输出结果。

编译和运行

确保你已经安装并配置好了 CUDA 和 TensorRT,然后使用以下命令编译和运行代码:

g++ -std=c++11 -o yolov5_trt yolov5_trt.cpp -lnvinfer -lnvinfer_plugin -lcudart -lopencv_core -lopencv_imgcodecs -lopencv_imgproc
./yolov5_trt

通过以上步骤,你可以完成从模型训练到部署的整个流程,并使用 C++ 代码进行人脸检测的推理。你可以根据需要进一步优化和扩展代码。

posted @ 2024-07-13 16:52  lvdongjie-avatarx  阅读(30)  评论(0编辑  收藏  举报