vs2022封装Dll动态链接库实现目标检测 (简单yolov5代码)

目录

一. 安装vs2022

二. 新建动态链接库项目

三. 配置opencv,和相应的属性配置

四. 代码


一. 安装vs2022

在vs2022中使用qt进行界面设计,两个软件项目互通_稷滼的博客-CSDN博客

二. 新建动态链接库项目

点击创建新项目,搜索dll找到动态链接库的项目新建

 

 创建后的样子

三. 配置opencv,和相应的属性配置

前提给自己opencv配置好环境变量

 根据自己安装的opencv路径添加

 VC++目录->包含目录:opencv\build\include\opencv2和opencv\build\include

 VC++目录->库目录:opencv\build\x64\vc15\lib和opencv\build\x64\vc15\bin

 连接器->输入->附加依赖项:opencv_world460d.lib (带d的是运行的Debug,不带d是Release)

 字符集改为多字节字符集

 C/C++->预编译头->预编译头:改为创建(/Yc),后期根据自己需要更改,也可以把预编译头文件中的.h文件去掉

四. 代码

创建头文件和源文件,名字随意

//yolo.h
#pragma once
#ifndef MY_HEADER_H
#define MY_HEADER_H
#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
#include "windows.h"

using namespace std;
using namespace cv;

const int INPUT_WIDTH = 640;
const int INPUT_HEIGHT = 640;
const float SCORE_THRESHOLD = 0.5;
const float NMS_THRESHOLD = 0.45;
const float CONFIDENCE_THRESHOLD = 0.45;

extern "C" _declspec(dllexport) void pre_process(cv::Mat & image, cv::Mat & blob);

extern "C" _declspec(dllexport) void a_process(cv::Mat & blob, cv::dnn::Net & net, std::vector<cv::Mat>&outputs);

extern "C" _declspec(dllexport) void draw_result(cv::Mat & image, std::string label, cv::Rect box);

extern "C" _declspec(dllexport) cv::Mat post_process(cv::Mat& image, std::vector<cv::Mat>& outputs, std::vector<std::string>& class_name);

extern "C" _declspec(dllexport) int main();


#endif
//yolo.cpp
#include "yolo.h"
#include "pch.h"


void pre_process(cv::Mat& image, cv::Mat& blob)
{
    cv::dnn::blobFromImage(image, blob, 1. / 255., cv::Size(INPUT_WIDTH, INPUT_HEIGHT), cv::Scalar(), true, false);
}
void a_process(cv::Mat& blob, cv::dnn::Net& net, std::vector<cv::Mat>& outputs)
{
    net.setInput(blob);
    net.forward(outputs, net.getUnconnectedOutLayersNames());
}

void draw_result(cv::Mat& image, std::string label, cv::Rect box)
{
    cv::rectangle(image, box, cv::Scalar(255, 0, 0), 2);
    int baseLine;
    cv::Size label_size = cv::getTextSize(label, 0.8, 0.8, 1, &baseLine);
    cv::Point tlc = cv::Point(box.x, box.y);
    cv::Point brc = cv::Point(box.x, box.y + label_size.height + baseLine);
    cv::putText(image, label, cv::Point(box.x, box.y), cv::FONT_HERSHEY_SIMPLEX, 0.8, cv::Scalar(0, 255, 255), 1);
}
cv::Mat post_process(cv::Mat& image, std::vector<cv::Mat>& outputs, std::vector<std::string>& class_name)
{
    std::vector<int> class_ids;
    std::vector<float> confidences;
    std::vector<cv::Rect> boxes;

    float x_factor = (float)image.cols / INPUT_WIDTH;
    float y_factor = (float)image.rows / INPUT_HEIGHT;

    float* data = (float*)outputs[0].data;

    const int dimensions = 85;
    const int rows = 25200;
    for (int i = 0; i < rows; ++i)
    {
        float confidence = data[4];
        if (confidence >= CONFIDENCE_THRESHOLD)
        {
            float* classes_scores = data + 5;
            cv::Mat scores(1, class_name.size(), CV_32FC1, classes_scores);
            cv::Point class_id;
            double max_class_score;
            cv::minMaxLoc(scores, 0, &max_class_score, 0, &class_id);
            if (max_class_score > SCORE_THRESHOLD)
            {
                float x = data[0];
                float y = data[1];
                float w = data[2];
                float h = data[3];
                int left = int((x - 0.5 * w) * x_factor);
                int top = int((y - 0.5 * h) * y_factor);
                int width = int(w * x_factor);
                int height = int(h * y_factor);
                boxes.push_back(cv::Rect(left, top, width, height));
                confidences.push_back(confidence);
                class_ids.push_back(class_id.x);
            }
        }
        data += dimensions;
    }

    std::vector<int> indices;
    cv::dnn::NMSBoxes(boxes, confidences, SCORE_THRESHOLD, NMS_THRESHOLD, indices);
    for (int i = 0; i < indices.size(); i++)
    {
        int idx = indices[i];
        cv::Rect box = boxes[idx];
        std::string label = class_name[class_ids[idx]] + ":" + cv::format("%.2f", confidences[idx]);
        draw_result(image, label, box);
    }
    return image;
}


int main()
{
    std::vector<std::string> class_name = { "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" ,"toothbrush" };
    std::string line;

    //输入一个自己的视频路径,也可以加图片
    cv::VideoCapture cap("C:/Users/le/Desktop/ceshi.mp4");
    cv::Mat image, blob;

    while (cap.read(image))
    {
        pre_process(image, blob);
        cv::dnn::Net net = cv::dnn::readNet("C:/Users/le/Desktop/yolov5/yolov5-cls-det-seg-opencv-main/yolov5n-det.onnx");
        std::vector<cv::Mat> detections;
        a_process(blob, net, detections);

        cv::Mat result = post_process(image, detections, class_name);
        cv::imshow("detection", result);
        if (waitKey(25) == 27) {

            break;
        }
    }
    cap.release();

    return 0;
}

 “extern”关键字是C/C++中用来声明外部变量或函数的关键字,它告诉编译器这个变量或函数在其他文件中定义,需要在当前文件中使用。因为在C/C++中,所有变量和函数默认都是内部的,也就是智能在当前文件中使用,如果要在其他文件中使用,需要使用extern关键字来声明。

“_declspec(dllexport)”是Windows平台特有的关键字,用于在编写动态链接库(DLL)时,指定导出函数或变量。在windows平台上,动态链接库的函数和变量需要使用_declspec(dllexport)关键字进行声明,一遍再DLL中进行导出。这样做可以使得其他程序可以调用这个DLL中的函数或变量。

总之,extern “C” _declspec(dllexport)是用来再C/C++语言中定义并导出函数或变量到动态链接库中的关键字。

如果自己的视频过大可以再代码中调整大小

cv::resize(result, result, cv::Size(680, 560));   

 调整好代码后,右击自己创建的项目,生成或重新生成。

 跟这个差不多就是创建成功,显示的路径就是你的动态链接库所在的位置。

链接: https://pan.baidu.com/s/1HHbGwC62KG1skNc5ocvSXA

提取码: rjaz

这是代码中onnx模型

 右击解决方案,添加新项目,整个空项目就可以

属性配置opencv

图中附加包含目录添加动态链接库中代码所在的路径(yolo.h和yolo.cpp)

 

 图中附加库目录添加生成的动态链接库所在的路径

附加依赖项添加生成的lib的名称

#pragma comment(dll,"Dll1.dll")       添加自己的名称生成后运行

效果

有任何问题,评论区

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
好的,下面是一个简单的示例代码,仅供参考: ```c++ #include <iostream> #include <vector> #include <opencv2/opencv.hpp> #include <onnxruntime_cxx_api.h> class YOLOv5 { public: YOLOv5(const std::string& model_path) { // 创建会话 Ort::SessionOptions options; options.SetIntraOpNumThreads(1); options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED); session_ = Ort::Session(env_, model_path.c_str(), options); } std::vector<cv::Rect> detect(const cv::Mat& image) { // 预处理图像 cv::Mat resized_image; cv::resize(image, resized_image, cv::Size(input_size_, input_size_)); cv::Mat float_image; resized_image.convertTo(float_image, CV_32FC3, 1.0 / 255.0); float* input_data = float_image.ptr<float>(); // 准备输入张量 Ort::MemoryInfo input_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU); std::vector<int64_t> input_shape = {1, 3, input_size_, input_size_}; Ort::Value input_tensor = Ort::Value::CreateTensor<float>(input_info, input_data, input_shape.data(), input_shape.size()); // 准备输出张量 Ort::MemoryInfo output_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU); std::vector<const char*> output_names = {"output"}; std::vector<int64_t> output_shape = {1, 25200, 85}; std::vector<float> output_data(25200 * 85); // 运行模型 Ort::RunOptions run_options; session_.Run(run_options, &input_names_[0], &input_tensor, 1, &output_names[0], 1, &output_info, &output_data[0], output_data.size()); // 解析输出张量 std::vector<cv::Rect> detections; for (int i = 0; i < 25200; i++) { float* data = &output_data[i * 85]; int class_id = std::max_element(data + 5, data + 85) - data - 5; float confidence = data[class_id + 5]; if (confidence >= confidence_threshold_) { int x1 = static_cast<int>((data[0] - data[2] / 2.0) * image.cols); int y1 = static_cast<int>((data[1] - data[3] / 2.0) * image.rows); int x2 = static_cast<int>((data[0] + data[2] / 2.0) * image.cols); int y2 = static_cast<int>((data[1] + data[3] / 2.0) * image.rows); detections.emplace_back(x1, y1, x2 - x1, y2 - y1); } } return detections; } private: Ort::Env env_{ORT_LOGGING_LEVEL_ERROR, "yolov5"}; Ort::Session session_; int input_size_ = 640; float confidence_threshold_ = 0.5; std::vector<const char*> input_names_ = {"input"}; }; ``` 这个类使用了 ONNX Runtime C++ API,可以加载 ONNX 模型并进行推理。在这个示例中,模型的输入张量名为 "input",输出张量名为 "output",模型的输入尺寸为 640x640,置信度阈值为 0.5。 在使用时,只需要创建 YOLOv5 对象并调用 detect 方法即可: ```c++ YOLOv5 yolo("yolov5.onnx"); cv::Mat image = cv::imread("test.jpg"); std::vector<cv::Rect> detections = yolo.detect(image); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

稷滼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值