Tabla de contenido
2. Cree un nuevo proyecto de biblioteca de vínculos dinámicos
3. Configure opencv y la configuración de atributos correspondiente
1. Instalar vs2022
2. Cree un nuevo proyecto de biblioteca de vínculos dinámicos
Haga clic para crear un nuevo proyecto, busque dll para encontrar el nuevo proyecto de la biblioteca de enlaces dinámicos
Cómo se ve después de la creación
3. Configure opencv y la configuración de atributos correspondiente
La premisa es configurar las variables de entorno para opencv por ti mismo.
Agregue de acuerdo con la ruta opencv que instaló
Directorio VC++ -> incluir directorio: opencv\build\include\opencv2 y opencv\build\include
Directorio VC++ -> directorio de la biblioteca: opencv\build\x64\vc15\lib y opencv\build\x64\vc15\bin
Conector -> Entrada -> Dependencias adicionales: opencv_world460d.lib (con d está ejecutando Debug, sin d es Release)
CONJUNTO DE CARACTERES A CONJUNTO DE CARACTERES MULTIBYTE
C/C++->Encabezado precompilado->Encabezado precompilado: Cree (/Yc) en su lugar, cámbielo más tarde según sus propias necesidades o elimine el archivo .h en el archivo de encabezado precompilado
4. Código
Cree archivos de encabezado y fuente con nombres arbitrarios
//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;
}
La palabra clave "extern" es una palabra clave que se usa en C/C++ para declarar variables o funciones externas. Le dice al compilador que esta variable o función está definida en otros archivos y debe usarse en el archivo actual. Porque en C/C++, todas las variables y funciones son internas por defecto, es decir, solo se pueden usar en el archivo actual, si se quieren usar en otros archivos, deben declararse con la palabra clave extern.
"_declspec(dllexport)" es una palabra clave específica de la plataforma Windows, que se utiliza para especificar la función o variable de exportación al escribir una biblioteca de vínculos dinámicos (DLL). En la plataforma de Windows, las funciones y variables de la biblioteca de vínculos dinámicos deben declararse con la palabra clave _declspec (dllexport) y luego exportarse nuevamente en la DLL. Si lo hace, permite que otros programas llamen a funciones o variables en esta DLL.
En resumen, extern "C" _declspec(dllexport) es una palabra clave utilizada para definir y exportar funciones o variables a la biblioteca de vínculos dinámicos en lenguaje C/C++.
Si su video es demasiado grande, puede cambiar su tamaño en el código
cv::resize(resultado, resultado, cv::Size(680, 560));
Después de ajustar el código, haga clic con el botón derecho en el proyecto que creó, generó o reconstruyó.
Similar a esto significa que la creación es exitosa y la ruta que se muestra es donde se encuentra su biblioteca de vínculos dinámicos.
Enlace: https://pan.baidu.com/s/1HHbGwC62KG1skNc5ocvSXA
Código de extracción: rjaz
Este es el modelo onnx en el código.
Haga clic derecho en la solución, agregue un nuevo proyecto, todo el proyecto vacío está bien
Configuración de propiedades opencv
El directorio de inclusión adicional en la figura agrega la ruta donde se encuentra el código en la biblioteca de vínculos dinámicos (yolo.h y yolo.cpp)
El directorio de biblioteca adicional en la figura agrega la ruta donde se encuentra la biblioteca de enlace dinámico generada
Las dependencias adicionales agregan el nombre de la librería generada
#pragma comment(dll,"Dll1.dll") Agregue su propio nombre para ejecutar después de la generación
Efecto
Cualquier duda, área de comentarios.