欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在C++中使用YOLO的四種實現方式

 更新時間:2025年06月26日 09:56:54   作者:LeonDL168  
隨著計算機視覺技術的不斷發(fā)展,目標檢測在許多應用領域都起到了重要作用,Yolo是一種流行的實時目標檢測算法,其以高效的速度和較高的準確率而聞名,本文將介紹在C++中使用YOLO的幾種方式,需要的朋友可以參考下

在C++中使用YOLO進行目標檢測主要有以下幾種方式,每種方式都有其特點和適用場景:

方式一:使用OpenCV DNN模塊(最簡單)

特點:無需依賴Darknet,僅需OpenCV庫,支持ONNX模型,跨平臺兼容。

適用場景:快速原型開發(fā)、CPU/GPU通用部署。

步驟:

轉換模型:將YOLOv5/YOLOv8導出為ONNX格式。

# YOLOv5
python export.py --weights yolov5s.pt --include onnx

# YOLOv8
yolo export model=yolov8n.pt format=onnx

C++代碼實現

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <iostream>
#include <vector>

using namespace cv;
using namespace dnn;
using namespace std;

struct Detection {
    int classId;
    float confidence;
    Rect box;
};

int main() {
    // 加載模型
    Net net = readNet("yolov5s.onnx");
    net.setPreferableBackend(DNN_BACKEND_OPENCV);
    net.setPreferableTarget(DNN_TARGET_CPU);  // 或 DNN_TARGET_CUDA

    // 讀取圖像
    Mat image = imread("test.jpg");
    Mat blob;
    blobFromImage(image, blob, 1/255.0, Size(640, 640), Scalar(), true, false);
    net.setInput(blob);

    // 前向傳播
    vector<Mat> outputs;
    net.forward(outputs, net.getUnconnectedOutLayersNames());

    // 解析輸出
    vector<int> classIds;
    vector<float> confidences;
    vector<Rect> boxes;
    float* data = (float*)outputs[0].data;
    
    for (int i = 0; i < outputs[0].rows; ++i) {
        Mat scores = outputs[0].row(i).colRange(5, outputs[0].cols);
        Point classIdPoint;
        double confidence;
        minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
        
        if (confidence > 0.4) {
            int centerX = (int)(data[i * 85 + 0] * image.cols);
            int centerY = (int)(data[i * 85 + 1] * image.rows);
            int width = (int)(data[i * 85 + 2] * image.cols);
            int height = (int)(data[i * 85 + 3] * image.rows);
            int left = centerX - width / 2;
            int top = centerY - height / 2;
            
            classIds.push_back(classIdPoint.x);
            confidences.push_back((float)confidence);
            boxes.push_back(Rect(left, top, width, height));
        }
    }

    // 非極大值抑制
    vector<int> indices;
    NMSBoxes(boxes, confidences, 0.4, 0.5, indices);
    
    // 繪制結果
    for (int idx : indices) {
        rectangle(image, boxes[idx], Scalar(0, 255, 0), 2);
        string label = format("class: %d, conf: %.2f", classIds[idx], confidences[idx]);
        putText(image, label, Point(boxes[idx].x, boxes[idx].y - 10), 
                FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 0), 2);
    }

    imshow("Detection", image);
    waitKey(0);
    return 0;
}

編譯命令

g++ yolo_opencv.cpp -o yolo `pkg-config --cflags --libs opencv4`

方式二:使用Darknet框架(原生支持)

特點:YOLO官方框架,支持C/C++接口,性能優(yōu)化好,但依賴復雜。

適用場景:需要完整復現YOLO訓練和推理流程。

步驟:

編譯Darknet

git clone https://github.com/AlexeyAB/darknet
cd darknet
make  # 修改Makefile以啟用CUDA/CUDNN

C++代碼實現

#include "darknet.h"
#include <iostream>

using namespace std;

int main() {
    // 加載網絡
    network* net = load_network("cfg/yolov4.cfg", "yolov4.weights", 0);
    set_batch_network(net, 1);
    
    // 加載圖像
    image im = load_image_color("test.jpg", 0, 0);
    image sized = letterbox_image(im, net->w, net->h);
    
    // 前向傳播
    layer l = net->layers[net->n - 1];
    float* X = sized.data;
    network_predict(net, X);
    
    // 解析結果
    int nboxes = 0;
    detection* dets = get_network_boxes(net, im.w, im.h, 0.5, 0.5, 0, 1, &nboxes);
    do_nms_sort(dets, nboxes, l.classes, 0.45);
    
    // 繪制結果
    // ...
    
    // 釋放資源
    free_detections(dets, nboxes);
    free_image(im);
    free_image(sized);
    free_network(net);
    
    return 0;
}

編譯命令

g++ yolo_darknet.cpp -o yolo -I/path/to/darknet/include -L/path/to/darknet/lib -ldarknet -lpthread -lcuda -lcudnn -lopencv_core -lopencv_imgproc -lopencv_imgcodecs

方式三:使用TensorRT加速(高性能)

特點:NVIDIA官方推理優(yōu)化工具,專為GPU設計,速度最快。

適用場景:嵌入式設備(Jetson)或GPU服務器上的高性能部署。

步驟:

轉換模型:將ONNX轉換為TensorRT引擎:

import tensorrt as trt

def build_engine(onnx_path, engine_path):
    logger = trt.Logger(trt.Logger.WARNING)
    builder = trt.Builder(logger)
    network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
    parser = trt.OnnxParser(network, logger)
    
    with open(onnx_path, 'rb') as model:
        parser.parse(model.read())
    
    config = builder.create_builder_config()
    config.max_workspace_size = 1 << 30  # 1GB
    config.set_flag(trt.BuilderFlag.FP16)  # 啟用FP16
    
    engine = builder.build_engine(network, config)
    with open(engine_path, 'wb') as f:
        f.write(engine.serialize())
    return engine

build_engine("yolov5s.onnx", "yolov5s.engine")

C++代碼實現

#include <NvInfer.h>
#include <NvOnnxParser.h>
#include <opencv2/opencv.hpp>
#include <cuda_runtime_api.h>

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

int main() {
    // 加載引擎
    Logger logger;
    std::ifstream file("yolov5s.engine", std::ios::binary);
    std::vector<char> engineData((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
    
    nvinfer1::IRuntime* runtime = nvinfer1::createInferRuntime(logger);
    nvinfer1::ICudaEngine* engine = runtime->deserializeCudaEngine(engineData.data(), engineData.size());
    nvinfer1::IExecutionContext* context = engine->createExecutionContext();
    
    // 準備輸入數據
    cv::Mat image = cv::imread("test.jpg");
    cv::Mat input = preprocess(image, 640, 640);  // 自定義預處理函數
    
    // 分配GPU內存
    void* buffers[2];
    cudaMalloc(&buffers[0], 3 * 640 * 640 * sizeof(float));
    cudaMalloc(&buffers[1], 25200 * 85 * sizeof(float));
    
    // 拷貝數據到GPU
    cudaMemcpy(buffers[0], input.data, 3 * 640 * 640 * sizeof(float), cudaMemcpyHostToDevice);
    
    // 執(zhí)行推理
    context->executeV2(buffers);
    
    // 拷貝結果回CPU
    std::vector<float> output(25200 * 85);
    cudaMemcpy(output.data(), buffers[1], 25200 * 85 * sizeof(float), cudaMemcpyDeviceToHost);
    
    // 解析結果
    // ...
    
    // 釋放資源
    cudaFree(buffers[0]);
    cudaFree(buffers[1]);
    context->destroy();
    engine->destroy();
    runtime->destroy();
    
    return 0;
}

方式四:使用libtorch(PyTorch C++前端)

特點:直接加載PyTorch模型,無需轉換,支持動態(tài)圖。

適用場景:需要與PyTorch訓練代碼無縫銜接的場景。

步驟:

導出TorchScript模型

import torch
model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True)
model.eval()
traced_script_module = torch.jit.trace(model, torch.rand(1, 3, 640, 640))
traced_script_module.save("yolov5s_scripted.pt")

C++代碼實現

#include <torch/script.h>
#include <opencv2/opencv.hpp>

int main() {
    // 加載模型
    torch::jit::script::Module module = torch::jit::load("yolov5s_scripted.pt");
    module.to(at::kCUDA);  // 若有GPU
    
    // 準備輸入
    cv::Mat image = cv::imread("test.jpg");
    cv::Mat input = preprocess(image, 640, 640);  // 轉換為[0,1]的浮點數
    
    // 轉換為Tensor
    torch::Tensor tensor = torch::from_blob(input.data, {1, 3, 640, 640}, torch::kFloat32);
    tensor = tensor.to(at::kCUDA);  // 若有GPU
    
    // 前向傳播
    std::vector<torch::jit::IValue> inputs;
    inputs.push_back(tensor);
    torch::Tensor output = module.forward(inputs).toTensor();
    
    // 解析結果
    // ...
    
    return 0;
}

性能對比

方式速度(FPS)依賴復雜度部署難度靈活性
OpenCV DNN簡單
Darknet中等
TensorRT極高復雜
libtorch中高中等

選擇建議

  • 快速開發(fā):選OpenCV DNN。
  • 極致性能:選TensorRT。
  • 完整功能:選Darknet。
  • PyTorch生態(tài):選libtorch。

到此這篇關于在C++中使用YOLO的四種實現方式的文章就介紹到這了,更多相關C++使用YOLO模型內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C#調用SQLite的詳細代碼舉例

    C#調用SQLite的詳細代碼舉例

    SQLite是一個輕量級、跨平臺的關系型數據庫,在小型項目中,方便,易用,同時支持多種開發(fā)語言,這篇文章主要給大家介紹了關于C#調用SQLite的相關資料,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-07-07
  • C# networkcomms 3.0實現模擬登陸總結

    C# networkcomms 3.0實現模擬登陸總結

    這篇文章主要介紹了C# networkcomms 3.0實現模擬登陸總結,需要的朋友可以參考下
    2017-06-06
  • C#中的Task.WaitAll和Task.WaitAny方法介紹

    C#中的Task.WaitAll和Task.WaitAny方法介紹

    這篇文章介紹了C#中的Task.WaitAll和Task.WaitAny方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • winform實現拖動文件到窗體上的方法

    winform實現拖動文件到窗體上的方法

    這篇文章主要介紹了winform實現拖動文件到窗體上的方法,以實例分析了C#中WinForm操作窗體及文件的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • c# 剔除sql語句''尾巴''的五種方法

    c# 剔除sql語句''尾巴''的五種方法

    這篇文章主要介紹了c# 剔除sql語句'尾巴'的五種方法,
    2020-11-11
  • C#實現簡單的登錄界面

    C#實現簡單的登錄界面

    我們在使用C#做項目的時候,基本上都需要制作登錄界面,那么今天我們就來一步步看看,如果簡單的實現登錄界面呢,本文給出2個例子,由簡入難,希望大家能夠喜歡。
    2015-11-11
  • C# 通過同步和異步實現優(yōu)化做早餐的時間

    C# 通過同步和異步實現優(yōu)化做早餐的時間

    本文以一個簡單的小例子—如何做一頓早餐及如何優(yōu)化做早餐的時間來讓大家具體了解一下同步和異步方法的區(qū)別,需要的朋友可以參考一下
    2021-12-12
  • C#使用StreamWriter寫入文件的方法

    C#使用StreamWriter寫入文件的方法

    這篇文章主要介紹了C#使用StreamWriter寫入文件的方法,涉及C#中StreamWriter類操作文件的相關技巧,需要的朋友可以參考下
    2015-05-05
  • C#使用符號表實現查找算法

    C#使用符號表實現查找算法

    本文詳細講解了C#使用符號表實現查找算法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-04-04
  • Entity Framework主從表數據加載方式

    Entity Framework主從表數據加載方式

    這篇文章介紹了Entity Framework主從表數據加載方式,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06

最新評論