[Aprendizaje profundo] [Opencv] Python/C++ llama al modelo onnx [Conceptos básicos]
Consejo: El blogger ha seleccionado muchas publicaciones de blogs de grandes y las ha probado personalmente para comprobar su eficacia. Comparte sus notas e invita a todos a estudiarlas y discutirlas juntos.
Directorio de artículos
Prefacio
OpenCV es una biblioteca de software multiplataforma de visión por computadora y aprendizaje automático (código abierto) publicada bajo la licencia BSD y puede ejecutarse en los sistemas operativos Linux, Windows, Android y Mac OS. El modelo entrenado en pytorch se puede exportar usando ONNX y luego cargarlo directamente usando el módulo dnn en opencv.
Directorio de aprendizaje de la serie:
[CPU] Explicación detallada del proceso del modelo Pytorch al modelo ONNX
[GPU] Explicación detallada del proceso del modelo Pytorch al formato ONNX
[modelo ONNX] Implementación rápida
[modelo ONNX] Implementación rápida de subprocesos múltiples
[modelo ONNX] Opencv llama a nx
Versión de PythonOpenCV
Instale OpenCV en la plataforma Windows
El blogger instaló el entorno anaconda en el entorno win10 y luego creó el entorno openCV necesario para ejecutar el modelo onnx.
# 搭建opencv环境
conda create -n opencv_onnx python=3.10 -y
# 激活环境
activate opencv_onnx
# 安装opencv
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
Ver versión opencv
import cv2
cv2.__version__
opencv llama al modelo onnx
Ahora el código deja de lado cualquier dependencia relacionada con pytorch y onnx, y solo usa opencv para completar todo el proceso de inferencia.
import cv2
import numpy as np
def normalizeImage(image,mean,std):
normalized = image.astype(np.float32)
normalized = normalized / 255.0 - mean
normalized = normalized / std
return normalized
def main():
# 读取图片
image = cv2.imread(r"./animal-1.jpg")
# 将BGR图像转换为RGB格式
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# 获取图像的大小
ori_w, ori_h, = image.shape[0], image.shape[1]
# 指定调整后的大小
new_width = 416
new_height = 416
# 图片尺寸缩放
resized_img = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_AREA)
# 定义每个通道的归一化参数
mean = np.array([0.485, 0.456, 0.406]).astype(np.float32) # 均值
std = np.array([0.229, 0.224, 0.225]).astype(np.float32) # 标准差
# 图片归一化
normalized = normalizeImage(resized_img, mean, std)
# 加载ONNX模型
net = cv2.dnn.readNetFromONNX("PFNet.onnx") # 加载训练好的识别模型
# onnx是多输出,每个输出都会对应一个name,因此需要获取所有输出的name
output_layer_names = net.getUnconnectedOutLayersNames()
blob = cv2.dnn.blobFromImage(normalized) # 由图片加载数据 这里还可以进行缩放、归一化等预处理
# 将Blob设置为模型的输入
net.setInput(blob)
# 运行前向传播,将所有输出name作为参数传递
out = net.forward(output_layer_names)
out = np.squeeze(out[3]) * 255.0
output = cv2.resize(out, (ori_h, ori_w), interpolation=cv2.INTER_AREA)
# 保存图像
cv2.imwrite('saved_opencv_python_image.png', output)
if __name__ == '__main__':
main()
Versión C++ OpenCV
Instale OpenCV en la plataforma Windows
Descargue la dirección del archivo de instalación del sitio web oficial . El blogger usa la versión opencv-4.8.0-windows.exe y hace doble clic para ejecutarlo y descomprimirlo para obtener los siguientes archivos:
Open VS 2019: cree un nuevo proyecto--- ->Aplicación de consola---->Proyecto de configuración ----> Ruta del proyecto y marque "Colocar la solución y el proyecto en el mismo directorio ----> Haga clic en Crear.
Establezca la ruta de OpenCV: Proyecto ----> Propiedades.
Agregar Directorio de inclusión adicional: Depuración | x64 ---->C/C+±—>General---->Directorios de inclusión adicionales.
D:\C++_demo\opencv\build\x64\vc16\bin
D:\C++_demo\opencv\build\bin
D:\C++_demo\opencv\build\include
D:\C++_demo\opencv\build\include\opencv2
Vinculador: Depurar | x64---->Enlazador---->General---->Directorios de inclusión adicionales.
D:\C++_demo\opencv\build\x64\vc16\lib
Vinculador: Depurar | x64---->Enlazador---->Entrada---->Dependencias adicionales.
Busque los archivos para dependencias adicionales en D:\C++_demo\opencv\build\x64\vc16\lib.
opencv_world480d.lib
Para probar en modo Debug x64, copie el archivo opencv_world480d.dll con d al directorio de depuración de su proyecto.
Cuando no hay un directorio de depuración, debe ejecutar el código en modo Debug | x64.
D:\C++_demo\opencv\build\x64\vc16\bin
===>
D:\C++_demo\opencv_onnx\x64\Debug
El blogger aquí instaló la versión de depuración para facilitar la depuración. Los lectores pueden instalar la versión de lanzamiento, solo necesitan cambiar Depurar |
opencv llama al modelo onnx
Fácil de usar
Aquí hay una verificación simple de si opencv se instaló exitosamente. Es adecuado para muchas personas, incluidos blogueros que no están familiarizados con C ++. El código completa la lectura y visualización de imágenes simples.
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("./animal-1.jpg");
//没有图像输入
if (src.empty()) {
printf("....\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO);
imshow("输入窗口", src);
waitKey(0);
destroyAllWindows();
return 0;
}
Llame al modelo onnx
Después de convertir la versión Python de opencv a la versión c ++ correspondiente, descubrimos que los efectos de salida son exactamente los mismos: el modelo onnx se puede utilizar como una interfaz c ++ para que lo llamen otras aplicaciones.
#include <iostream>
#include <string>
#include <vector>
#include<opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
using namespace std;
cv::Mat normalizeImage(const cv::Mat& image, const cv::Scalar& mean, const cv::Scalar& std) {
cv::Mat normalized;
image.convertTo(normalized, CV_32F);
cv::subtract(normalized / 255.0, mean, normalized);
cv::divide(normalized, std, normalized);
return normalized;
}
int main()
{
// 读取图片
cv::Mat bgrImage = cv::imread("./animal-1.jpg", cv::IMREAD_COLOR);
// 图片格式转化bgr-->rgb
cv::Mat rgbImage;
cv::cvtColor(bgrImage, rgbImage, cv::COLOR_BGR2RGB);
// 获取图像的大小
cv::Size originalSize(rgbImage.cols, rgbImage.rows);
cv::Mat resizedImage;
// 定义目标图像大小
cv::Size targetSize(416, 416);
//图片尺寸缩放
cv::resize(rgbImage, resizedImage, targetSize, 0, 0, cv::INTER_AREA);
// 定义每个通道的归一化参数
cv::Scalar mean(0.485, 0.456, 0.406); // 均值
cv::Scalar std(0.229, 0.224, 0.225); // 标准差
// 图片归一化
cv::Mat normalized = normalizeImage(resizedImage, mean, std);
// 加载ONNX模型
cv::dnn::Net net = cv::dnn::readNetFromONNX("D:/C++_demo/opencv_onnx/PFNet.onnx");
cv::Mat blob = cv::dnn::blobFromImage(normalized);
// 将Blob设置为模型的输入
net.setInput(blob);
// 运行前向传播
std::vector<cv::Mat> output_probs;
// 获取多输出对应的名称
std::vector<cv::String> output_layer_names = net.getUnconnectedOutLayersNames();
net.forward(output_probs, output_layer_names);
cv::Mat prediction = output_probs[3];
cv::Mat mask;
cv::resize(prediction.reshape(1, 416) * 255.0, mask, originalSize, 0, 0, cv::INTER_AREA);
cv::imwrite("saved_opencv_c++_image.png", mask);
return 0;
}
Resumir
Presente el proceso de llamada al modelo ONNX mediante POpencv en Python y C++ de la manera más simple y detallada posible.