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 :

AlgorithmeDescription
KNNAlgorithme des K plus proches voisins, utilisé pour la classification et la régression.
SVMMachine à vecteurs de support, utilisée pour la classification et la régression.
Arbre de décisionUn algorithme de classification et de régression basé sur des arbres.
Forêt aléatoireUn algorithme d'apprentissage ensembliste basé sur plusieurs arbres de décision.
K-MeansAlgorithme 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 :

  1. Initialisation: Sélectionner aléatoirement K échantillons comme centres de clusters initiaux.
  2. Affectation: Affecter chaque échantillon au centre de cluster le plus proche.
  3. Mise à jour: Recalculer le point central de chaque cluster.
  4. 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 <opencv2/opencv.hpp>
#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 :

  1. Entraînement: Trouver un hyperplan optimal à partir des données d'entraînement.
  2. Prédiction: Utiliser le modèle entraîné pour classer de nouvelles données.

SVM dans OpenCV :

Exemple

#include <opencv2/opencv.hpp>
#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 :

  1. Calculer la matrice de covariance: Calculer la matrice de covariance de l'ensemble de données.
  2. 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.
  3. Sélectionner les composantes principales: Sélectionner les vecteurs propres correspondant aux K plus grandes valeurs propres comme composantes principales.
  4. 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 <opencv2/opencv.hpp>
#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/opencv.hpp>
#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/opencv.hpp>
#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/opencv.hpp>
#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.

Autres extensions