[Deep Learning] [Opencv] python/C++ appelle le modèle onnx [Bases]
Astuce : le blogueur a sélectionné de nombreux articles de blog de grands noms et les a personnellement testés pour vérifier leur efficacité. Il partage ses notes et invite tout le monde à les étudier et à en discuter ensemble.
Annuaire d'articles
Préface
OpenCV est une bibliothèque logicielle multiplateforme de vision par ordinateur et d'apprentissage automatique (open source) publiée sous licence BSD et peut fonctionner sur les systèmes d'exploitation Linux, Windows, Android et Mac OS. Le modèle formé dans pytorch peut être exporté à l'aide d'ONNX, puis directement chargé à l'aide du module dnn dans opencv.
Répertoire d'apprentissage de la série :
[CPU] Explication détaillée du modèle Pytorch vers le processus de modèle ONNX
[GPU] Explication détaillée du modèle Pytorch vers le processus de format ONNX
[Modèle ONNX] Déploiement rapide
[Modèle ONNX] Déploiement rapide multithread
[Modèle ONNX] Opencv appelle onnx
Version PythonOpenCV
Installer OpenCV sur la plateforme Windows
Le blogueur a installé l'environnement anaconda dans l'environnement win10 , puis a construit l'environnement openCV requis pour exécuter le modèle 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
Voir la version opencv
import cv2
cv2.__version__
opencv appelle le modèle onnx
Désormais, le code met de côté toutes les dépendances liées à pytorch et à onnx, et utilise uniquement opencv pour terminer l'ensemble du processus d'inférence.
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()
Version C++OpenCV
Installer OpenCV sur la plateforme Windows
Téléchargez l'adresse du fichier d'installation sur le site officiel . Le blogueur utilise la version opencv-4.8.0-windows.exe et double-cliquez pour l'exécuter et le décompresser pour obtenir les fichiers suivants :
Open VS 2019 : Créer un nouveau projet --- ->Application console---->Projet de configuration ----> Chemin du projet et cochez "Placer la solution et le projet dans le même répertoire ----> Cliquez sur Créer.
Définissez le chemin OpenCV : Projet ----> Propriétés.
Ajouter Répertoire d'inclusion supplémentaire : Debug | x64 ---->C/C+±—>Général---->Répertoires d'inclusion supplémentaires.
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
Linker : Debug | x64---->Linker---->Général---->Répertoires d'inclusion supplémentaires.
D:\C++_demo\opencv\build\x64\vc16\lib
Linker : Debug | x64---->Linker---->Entrée---->Dépendances supplémentaires.
Recherchez les fichiers pour les dépendances supplémentaires sous D:\C++_demo\opencv\build\x64\vc16\lib.
opencv_world480d.lib
Pour tester en mode Debug x64, copiez le fichier opencv_world480d.dll avec d dans le répertoire Debug de votre projet.
Lorsqu'il n'y a pas de répertoire Debug, vous devez exécuter le code en mode Debug | x64.
D:\C++_demo\opencv\build\x64\vc16\bin
===>
D:\C++_demo\opencv_onnx\x64\Debug
Le blogueur a installé ici la version de débogage pour faciliter le débogage. Les lecteurs peuvent installer la version finale. Il leur suffit de modifier le paramètre Debug |
opencv appelle le modèle onnx
Simple à utiliser
Voici une simple vérification pour savoir si opencv est installé avec succès. Il convient à de nombreuses personnes, y compris aux blogueurs qui ne sont pas familiers avec le C++. Le code complète la lecture et l'affichage d'images 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;
}
Appelez le modèle onnx
Après avoir converti la version python d'opencv en la version C++ correspondante, nous avons constaté que les effets de sortie sont exactement les mêmes.Le modèle onnx peut être utilisé comme interface C++ pour que d'autres applications puissent l'appeler.
#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;
}
Résumer
Présentez le processus d'appel du modèle ONNX par POpencv sous Python et C++ aussi simplement et en détail que possible.