Apprentissage automatique et apprentissage profond avec C++ OpenCV
OpenCV ne prend pas seulement en charge les tâches traditionnelles de vision par ordinateur, mais fournit également de riches fonctions d'apprentissage automatique et d'apprentissage profond, grâce auxquelles des tâches complexes telles que la classification d'images, la détection d'objets et la segmentation sémantique peuvent être réalisées.
Apprentissage automatique: OpenCV propose une variété d'algorithmes traditionnels d'apprentissage automatique, tels que KNN, SVM, arbres de décision, etc.
Apprentissage profond: le module DNN d'OpenCV prend en charge le chargement et l'exécution de modèles d'apprentissage profond pré-entraînés (tels que TensorFlow, PyTorch, Caffe, etc.)
Scénarios d'application de l'apprentissage automatique et de l'apprentissage profond
Classification d'images :
Utiliser des modèles d'apprentissage automatique ou d'apprentissage profond pour classer les images.
Scénarios d'application : classification d'images médicales, contrôle qualité industriel, etc.
Détection d'objets :
Utiliser des modèles d'apprentissage profond pour détecter des objets dans les images.
Scénarios d'application : conduite autonome, surveillance de sécurité, etc.
Segmentation sémantique :
Utiliser des modèles d'apprentissage profond pour classer chaque pixel d'une image.
Scénarios d'application : analyse d'images médicales, analyse d'images de télédétection, etc.
Algorithmes d'apprentissage automatique courants
OpenCV fournit les algorithmes d'apprentissage automatique courants suivants :
| Algorithme | Description |
|---|---|
| KNN | Algorithme des K plus proches voisins, utilisé pour la classification et la régression. |
| SVM | Machine à vecteurs de support, utilisée pour la classification et la régression. |
| Arbre de décision | Un algorithme de classification et de régression basé sur des arbres. |
| Forêt aléatoire | Un algorithme d'apprentissage ensembliste basé sur plusieurs arbres de décision. |
| K-Means | Algorithme de clustering, utilisé pour diviser les données en plusieurs groupes. |
Regroupement K-Means
Le clustering K-Means est un algorithme d'apprentissage non supervisé principalement utilisé pour diviser un ensemble de données en K clusters. Chaque cluster est constitué des échantillons les plus proches de son centre.
L'idée centrale de l'algorithme K-Means est d'optimiser itérativement les centres de clusters afin que la distance de chaque point d'échantillon à son centre de cluster soit minimisée.
Étapes d'implémentation :
- Initialisation: Sélectionner aléatoirement K échantillons comme centres de clusters initiaux.
- Affectation: Affecter chaque échantillon au centre de cluster le plus proche.
- Mise à jour: Recalculer le point central de chaque cluster.
- Itération: Répéter les étapes 2 et 3 jusqu'à ce que les centres des clusters ne changent plus ou que le nombre maximal d'itérations soit atteint.
K-Means dans OpenCV :
Exemple
#include <iostream>
int main() {
// Générer quelques données aléatoires
cv::Mat data(100, 2, CV_32F);
cv::randu(data, cv::Scalar(0, 0), cv::Scalaire(100, 100));
// Définir la valeur de K et les conditions d'itération
int K = 3;
cv::Mat labels, centers;
cv::kmeans(data, K, labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::MAX_ITER, 10, 1.0), 3, cv::KMEANS_PP_CENTERS, centers);
// Afficher les résultats
std::cout << "Étiquettes : " << labels << std::endl;
std::cout << "Centres : " << centers << std::endl;
return 0;
}
Dans le code ci-dessus, nous avons généré 100 points de données bidimensionnels et utilisé l'algorithme K-Means pour les répartir en 3 clusters.cv::kmeansLes paramètres de la fonction incluent les données, le nombre de clusters, les étiquettes, les conditions d'arrêt, etc.
Machine à vecteurs de support (SVM)
La machine à vecteurs de support (SVM) est un algorithme d'apprentissage supervisé principalement utilisé pour des tâches de classification et de régression.
L'idée centrale de SVM est de trouver un hyperplan qui maximise la marge entre les points d'échantillon de différentes classes.
Étapes d'implémentation :
- Entraînement: Trouver un hyperplan optimal à partir des données d'entraînement.
- Prédiction: Utiliser le modèle entraîné pour classer de nouvelles données.
SVM dans OpenCV :
Exemple
#include <iostream>
int main() {
// Générer des données d'entraînement
cv::Mat trainData = (cv::Mat_<float>(4, 2) << 1, 1, 1, 2, 2, 1, 2, 2);
cv::Mat labels = (cv::Mat_<int>(4, 1) << 1, 1, -1, -1);
// Créer un modèle SVM
cv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();
svm->setKernel(cv::ml::SVM::LINEAR);
svm->setType(cv::ml::SVM::C_SVC);
svm->setC(1);
// Entraîner le modèle
svm->train(trainData, cv::ml::ROW_SAMPLE, labels);
// Prédire de nouvelles données
cv::Mat testData = (cv::Mat_<float>(1, 2) << 1.5, 1.5);
float response = svm->predict(testData);
std::cout << "Étiquette prédite : " << response << std::endl;
return 0;
}
Dans le code ci-dessus, nous utilisons SVM pour classifier des données bidimensionnelles.
cv::ml::SVM::create()Utilisé pour créer le modèle SVM,trainLa méthode est utilisée pour entraîner le modèle,predictLa méthode est utilisée pour prédire la classe de nouvelles données.
Analyse en composantes principales (ACP)
L'analyse en composantes principales (ACP) est une technique de réduction de dimensionnalité principalement utilisée pour réduire la dimensionnalité d'un ensemble de données tout en conservant les principales caractéristiques des données.
L'ACP projette les données d'origine dans un nouveau système de coordonnées au moyen d'une transformation linéaire, de sorte que la variance des données dans le nouveau système de coordonnées soit maximisée.
Étapes d'implémentation :
- Calculer la matrice de covariance: Calculer la matrice de covariance de l'ensemble de données.
- Décomposition en valeurs propres: Effectuer une décomposition en valeurs propres sur la matrice de covariance pour obtenir les vecteurs propres et les valeurs propres.
- Sélectionner les composantes principales: Sélectionner les vecteurs propres correspondant aux K plus grandes valeurs propres comme composantes principales.
- Projection des données: Projeter les données originales sur les composantes principales pour obtenir les données de dimension réduite.
ACP dans OpenCV :
Exemple
#include <iostream>
int main() {
// Générer des données
cv::Mat data = (cv::Mat_<float>(4, 2) << 1, 2, 2, 3, 3, 4, 4, 5);
// Créer un objet ACP
cv::PCA pca(data, cv::Mat(), cv::PCA::DATA_AS_ROW, 1);
// Projeter les données
cv::Mat projected = pca.project(data);
std::cout << "Données projetées : " << projected << std::endl;
return 0;
}
Dans le code ci-dessus, nous utilisons PCA pour réduire la dimensionnalité de données bidimensionnelles.cv::PCALe constructeur de classe accepte les données d'entrée, le vecteur moyen, la disposition des données et le nombre de composantes principales retenues.projectLa méthode est utilisée pour projeter les données sur les composantes principales.
Open et Deep Learning
Avec l'application généralisée de l'apprentissage profond dans le domaine de la vision par ordinateur, OpenCV fournit également une prise en charge de l'apprentissage profond.
Grâce au module DNN d'OpenCV, les développeurs peuvent charger des modèles profonds pré-entraînés et effectuer des tâches telles que la classification d'images, la détection d'objets et la segmentation sémantique.
Chargement de modèles d'apprentissage profond pré-entraînés (DNN)
Le module DNN d'Open prend en charge le chargement de modèles pré-entraînés à partir de plusieurs frameworks d'apprentissage profond (tels que TensorFlow, Caffe, PyTorch, etc.).
Grâce au module DNN, les développeurs peuvent facilement intégrer des modèles d'apprentissage profond dans des applications C++.
Chargement du :
Exemple
#include <opencv2/dnn.hpp>
#include <iostream>
int main() {
// Charger un modèle Caffe pré-entraîné
cv::dnn::Net net = cv::dnn::readNetFromCaffe("deploy.prototxt", "model.caffemodel");
// Vérifier si le modèle a été chargé avec succès
if (net.empty()) {
std::cerr << "Échec du chargement du modèle !" << std::endl;
return -1;
}
std::cout << "Modèle chargé avec succès !" << std::endl;
return 0;
}
Dans le code ci-dessus, nous utilisonscv::dnn::readNetFromCaffela fonction pour charger un modèle Caffe.deploy.prototxtest le fichier de configuration du modèle,model.caffemodelest le fichier de poids du modèle.
Classification d'images, Détection d'objets, Segmentation sémantique
Le module DNN d'OpenCV prend en charge plusieurs tâches d'apprentissage profond, notamment la classification d'images, la détection d'objets et la segmentation sémantique. Ce qui suit est un exemple simple de classification d'images :
Classification d'images :
Exemple
#include <opencv2/dnn.hpp>
#include <iostream>
int main() {
// Charger un modèle Caffe pré-entraîné
cv::dnn::Net net = cv::dnn::readNetFromCaffe("deploy.prototxt", "model.caffemodel");
// Charger l'image
cv::Mat image = cv::imread("image.jpg");
if (image.empty()) {
std::cerr << "Échec du chargement de l'image !" << std::endl;
return -1;
}
// Prétraiter l'image
cv::Mat blob = cv::dnn::blobFromImage(image, 1.0, cv::Size(224, 224), cv::Scalaire(104, 117, 123));
// Définir l'entrée
net.setInput(blob);
// Propagation avant
cv::Mat prob = net.forward();
// Obtenir le résultat de classification
cv::Point classIdPoint;
double confidence;
cv::minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
int classId = classIdPoint.x;
std::cout << "ID de classe : " << classId << ", Confiance : " << confidence << std::endl;
return 0;
}
Dans le code ci-dessus, nous avons chargé un modèle Caffe et classé l'image d'entrée.cv::dnn::blobFromImageLa fonction est utilisée pour convertir l'image au format d'entrée du modèle,net.forward()est utilisée pour effectuer la propagation avant,cv::minMaxLocest utilisée pour obtenir le résultat de classification.
Exécution de modèles comme YOLO et SSD avec OpenCV
Le module DNN d'OpenCV prend également en charge l'exécution de modèles de détection d'objets tels que YOLO (You Only Look Once) et SSD (Single Shot MultiBox Detector).
Voici un exemple d'utilisation du modèle YOLO pour la détection d'objets :
Détection d'objets YOLO :
Exemple
#include <opencv2/dnn.hpp>
#include <iostream>
int main() {
// Charger le modèle YOLO']
cv::dnn::Net net = cv::dnn::readNetFromDarknet("yolov3.cfg", "yolov3.weights"']);
// Charger l'image
cv::Mat image = cv::imread("image.jpg");
if (image.empty()) {
std::cerr << "Échec du chargement de l'image !" << std::endl;
return -1;
}
// Prétraiter l'image
cv::Mat blob = cv::dnn::blobFromImage(image, 1/255.0, cv::Size(416, 416), cv::Scalar(0, 0, 0), true, false']);
// Définir l'entrée
net.setInput(blob);
// Propagation avant
std::vector<cv::Mat> outs'];
net.forward(outs, net.getUnconnectedOutLayersNames']());
// Analyser les résultats de détection']
for (size_t i = 0; i < outs.']size(); ++i) {
float* data = (float*)outs'][i].data;
for (int j = 0; j < outs'][i].rows; ++j, data += outs[i].cols']) {
cv::Mat scores = outs[i].row'](j).colRange(5, outs[i].cols']);
cv::Point classIdPoint;
double confidence;
cv::minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
if (confidence > 0.5) {
int centerX = (int)(data[0] * image.cols);
int centerY = (int)(data[1] * image.lignes);
int width = (int)(data[2] * image.cols);
int height = (int)(data[3] * image.lignes);
int left = centerX - width / 2;
int top = centerY - height / 2;
cv::rectangle(image, cv::Point(left, top), cv::Point(left + width, top + height), cv::Scalaire(0, 255, 0), 2);
}
}
}
// Afficher les résultats
cv::imshow("Détection", image);
cv::waitKey(0);
return 0;
}
Dans le code ci-dessus, nous avons chargé un modèle YOLO et effectué la détection d'objets sur l'image d'entrée.cv::dnn::readNetFromDarknetLa fonction est utilisée pour charger le modèle YOLO,net.forwardest utilisée pour effectuer la propagation avant,cv::rectangleest utilisée pour dessiner les boîtes de détection.