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

模型部署 - TensorRT 简介及人脸推理简单示例

     TensorRT是Nvidia开发的一个高性能深度学习推理引擎。 它主要用于优化和部署已经训练好的深度学习模型, 提高模型在NVIDIA GPU硬件上的推理性能。

  TensorRT的主要功能和特点包括:

   1. 模型优化

        TensorRT提供了一系列优化技术, 包括层融合, 张量格式化, kernel自动调优等, 可以大幅度提高模型在NVIDIA GPU上的推理性能。

  2. 硬件加速

     TensorRT深度集成了NVIDIA GPU硬件的底层特性, 可以充分发挥GPU的并行计算能力, 提供高性能的推理加速。

  3. 跨平台部署

     TensorRT支持在Windows, Linux和Jeson等多个平台部署优化后的模型, 方便用户在不同环境中使用。

 4. 丰富的API

    TensorRT提供了C++和Python两种语言的API, 开发者可以灵活的将TensorRT集成到自己的应用程序中。

 5. 支持多种模型格式

    TensorRT可以导出ONNX, Caffe, Tensorflow 等主流深度学习框架导出的模型, 并对其进行优化。

 6. 多硬件支持

    处理NVIDIA GPU, TensorRT也支持在NVIDIA Jesson嵌入式平台上部署优化的模型。

中的来说, TensorRT是NVIDIA专门为深度学习推理场景打造的一款高性能引擎, 广泛应用于需要部署深度学习模型的场景, 如自动驾驶, 智能视觉, 自然语言处理等。 掌握TensorRT的使用对于深度学习工程师来说是非常重要的技能。

以下是一个TensorRT结合C++进行人脸识别的示例代码:

这个示例将涵盖以下步骤:

  1. 使用 TensorFlow 或 PyTorch 训练好人脸检测和人脸特征提取的深度学习模型。
  2. 将模型转换为 ONNX 格式。
  3. 使用 TensorRT 优化 ONNX 模型,生成 TensorRT 引擎。
  4. 在 C++ 中使用 TensorRT API 加载优化后的模型,进行人脸检测和特征提取。
  5. 将检测到的人脸信息与特征向量输出。
#include <NvInfer.h>
#include <opencv2/opencv.hpp>

using namespace nvinfer1;

// 初始化 TensorRT 推理引擎
std::unique_ptr<ICudaEngine> initEngine(const std::string& onnx_path) {
    // 创建IBuilder 对象, 用于构建TensorRT引擎。
    IBuilder* builder = createInferBuilder(gLogger);
    // 创建网络
    INetworkDefinition* network = builder->createNetwork();
    // 创建ONNX解析器
    OnnxParser* parser = createOnnxParser(network);
    // 从指定的ONNX文件中解析拓扑网络 结果存储在network 
    parser->parseFromFile(onnx_path.c_str(), static_cast<int>(ILogger::Severity::kWARNING));
    // 设置批处理大小为1
    builder->setMaxBatchSize(1); 
    // 设置最大工作空间大小为1MB
    builder->setMaxWorkspaceSize(1 << 20);
    // 构建使用Builder对象,构建CUDA引擎
    std::unique_ptr<ICudaEngine> engine(builder->buildCudaEngine(network));
    
    // 清理网络定义和构建器,和解析器
    network->destroy();
    builder->destroy();
    parser->destroy();
    return engine;
}

// 使用 TensorRT 进行人脸检测和特征提取
std::vector<cv::Rect> detectFaces(cv::Mat& image, std::unique_ptr<ICudaEngine>& engine) {
    std::vector<cv::Rect> faces;
    // 将图像输入到 TensorRT 引擎进行推理
    // 获取人脸检测结果
    // 提取每个人脸的特征向量

    std::vector<cv::Rect> faces;

    // 1. 将输入图像转换为 TensorRT 引擎所需的格式
    cv::Mat resizedImage;
    cv::resize(image, resizedImage, cv::Size(300, 300));
    float* inputData = new float[300 * 300 * 3];
    for (int y = 0; y < 300; y++) {
        for (int x = 0; x < 300; x++) {
            cv::Vec3b pixel = resizedImage.at<cv::Vec3b>(y, x);
            inputData[y * 300 * 3 + x * 3 + 0] = (pixel[2] - 127.5) / 127.5;
            inputData[y * 300 * 3 + x * 3 + 1] = (pixel[1] - 127.5) / 127.5;
            inputData[y * 300 * 3 + x * 3 + 2] = (pixel[0] - 127.5) / 127.5;
        }
    }

    // 2. 创建 TensorRT 引擎执行上下文
    IExecutionContext* context = engine->createExecutionContext();

    // 3. 设置输入数据
    context->setBindingDimensions(0, Dims4(1, 3, 300, 300));
    void* bindings[] = { inputData };
    // 4. 执行 TensorRT 推理
    context->executeV2(bindings);

    // 5. 获取输出数据 ,输出张量的大小是 1 x 100 x 7
    // 1 表示批处理大小为 1
    // 100表示最多检测 100 个物体
    // 7表示每个检测框包含 7 个值(x(左上, 归一化), y(左上,归一化), width(归一化), height(归一化), confidence(整体置信度), class_id(类别ID), class_score(类别置信度))
    float* detectionOutput = new float[1 * 100 * 7];
    // 从 TensorRT 引擎的输出张量中将数据复制到我们之前分配的 detectionOutput 数组中
    // context->getOutputHandle(0) 获取了第一个(也是唯一一个)输出张量的句柄。由于我们只有一个输出张量,索引为 0。
    // copyToHost() 方法将输出张量的数据复制到 CPU 内存中的 detectionOutput 数组
    context->getOutputHandle(0)->copyToHost(detectionOutput);

    // 6. 解析人脸检测结果 遍历这个数组,解析每个检测框的信息(位置、大小、置信度、类别等)
    for (int i = 0; i < 100; i++) {
        float score = detectionOutput[i * 7 + 4];
        if (score > 0.5) {
            int x = static_cast<int>(detectionOutput[i * 7 + 0] * image.cols);
            int y = static_cast<int>(detectionOutput[i * 7 + 1] * image.rows);
            int width = static_cast<int>(detectionOutput[i * 7 + 2] * image.cols - x);
            int height = static_cast<int>(detectionOutput[i * 7 + 3] * image.rows - y);
            faces.push_back(cv::Rect(x, y, width, height));
        }
    }

    // 7. 释放资源
    delete[] inputData;
    delete[] detectionOutput;
    context->destroy();

    return faces;
}

int main() {
    std::unique_ptr<ICudaEngine> engine = initEngine("path/to/your/model.onnx");
    cv::Mat image = cv::imread("path/to/your/image.jpg");
    std::vector<cv::Rect> faces = detectFaces(image, engine);
    // 将检测到的人脸信息和特征向量输出
    return 0;
}

 

posted @ 2024-07-13 14:09  lvdongjie-avatarx  阅读(17)  评论(0编辑  收藏  举报