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")       添加自己的名称生成后运行

效果

有任何问题,评论区

猜你喜欢

转载自blog.csdn.net/jifanyyds/article/details/130734098