Traitement d'images avancé C++ OpenCV
Le traitement avancé d'images consiste à effectuer des tâches plus complexes sur la base du traitement d'images de base (comme le filtrage, la détection de contours, etc.), telles que la segmentation d'images, la détection de contours, les opérations morphologiques, le traitement d'histogrammes, et plus encore. Ces techniques sont largement utilisées dans des domaines tels que la détection d'objets, l'analyse d'images et le traitement d'images médicales.
Scénarios d'application du traitement avancé d'images
Analyse d'images médicales :
Utiliser des techniques de segmentation d'images pour extraire les régions lésionnelles.
Utiliser des opérations morphologiques pour supprimer le bruit.
Détection et suivi d'objets :
Utiliser la détection de contours et la correspondance de modèles pour localiser des objets.
Utiliser le traitement d'histogrammes pour améliorer les caractéristiques des objets.
Amélioration d'images :
Utiliser l'égalisation d'histogrammes pour améliorer le contraste de l'image.
Utilisez l'algorithme watershed pour séparer des objets qui se chevauchent.
Segmentation d'image
La segmentation d'image est une étape importante du traitement d'image. Elle divise une image en plusieurs régions ou objets pour une analyse et un traitement ultérieurs. Les méthodes courantes de segmentation d'image comprennent la segmentation par seuillage, la segmentation par contours et la segmentation par régions.
Segmentation par seuillage
La segmentation par seuillage est l'une des méthodes de segmentation d'image les plus simples. Elle classe les valeurs de pixels en différentes catégories en définissant un ou plusieurs seuils. Les méthodes courantes de segmentation par seuillage comprennent le seuillage global et le seuillage adaptatif.
Seuillage global
Le seuillage global utilise un seuil fixe pour diviser une image en premier plan et arrière-plan. OpenCV fournit lacv::thresholdfonction pour implémenter cela.
cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat dst;
cv::threshold(src, dst, 128, 255, cv::THRESH_BINARY);
Dans le code ci-dessus,128est le seuil,255est la valeur maximale des pixels,cv::THRESH_BINARYindique l'utilisation de la méthode de seuillage binaire.
Seuillage adaptatif
Le seuillage adaptatif ajuste dynamiquement le seuil en fonction des régions locales de l'image. OpenCV fournit lacv::adaptiveThresholdfonction pour implémenter cela.
cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat dst;
cv::adaptiveThreshold(src, dst, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 11, 2);
Dans le code ci-dessus,255est la valeur maximale des pixels,cv::ADAPTIVE_THRESH_MEAN_Cindique l'utilisation de la moyenne locale comme seuil,11est la taille du voisinage,2est la constante.
Segmentation basée sur les contours
La segmentation basée sur les contours segmente une image en détectant les contours dans l'image. Les algorithmes courants de détection de contours incluent la détection de contours de Canny et l'opérateur Sobel.
Détection de contours de Canny
La détection de contours de Canny est un algorithme de détection de contours à plusieurs étapes. OpenCV fournit lacv::Cannyfonction pour implémenter cela.
cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
cv::Mat edges;
cv::Canny(src, edges, 100, 200);
Dans le code ci-dessus,100et200sont les deux seuils de l'algorithme de Canny.
Segmentation basée sur les régions (algorithme de ligne de partage des eaux)
La segmentation basée sur les régions réalise la segmentation en divisant l'image en plusieurs régions. L'algorithme de ligne de partage des eaux est une méthode de segmentation basée sur les régions couramment utilisée.
Algorithme de ligne de partage des eaux
L'algorithme de ligne de partage des eaux traite l'image comme une carte topographique et la segmente en simulant la diffusion du flux d'eau. OpenCV fournit lacv::watershedfonction pour implémenter cela.
cv::Mat src = cv::imread("image.jpg");
cv::Mat markers = cv::Mat::zeros(src.size(), CV_32S);
cv::watershed(src, markers);
Dans le code ci-dessus,markersest la matrice de marqueurs, utilisée pour stocker le résultat de la segmentation.
Détection de contours
La détection de contours est une étape importante du traitement d'images. Elle est utilisée pour détecter les limites des objets dans une image. OpenCV fournit diverses fonctions pour la détection et le traitement des contours.
Recherche de contours
La recherche des contours est la première étape de la détection de contours. OpenCV fournit lacv::findContoursfonction pour implémenter cela.
cv::Mat src = cv::imread("image.jpg", cv::IMREAD_GRAYSCALE);
std::vector<std::vector<cv::Point>> contours;
std::vector<cv::Vec4i> hierarchy;
cv::findContours(src, contours, hierarchy, cv::RETR_TREE, cv::CHAIN_APPROX_SIMPLE);
Dans le code ci-dessus,contoursest le vecteur qui stocke les contours,hierarchyest le vecteur qui stocke la hiérarchie des contours.
Caractéristiques des contours
Les caractéristiques des contours incluent l'aire, le périmètre, la boîte englobante, et plus encore. OpenCV fournit diverses fonctions pour calculer ces caractéristiques.
Zone
L'aire est une caractéristique importante d'un contour. OpenCV fournit lacv::contourAreafonction pour calculer l'aire d'un contour.
double area = cv::contourArea(contours[0]);
Perimeter
Le périmètre est une autre caractéristique importante d'un contour. OpenCV fournit lacv::arcLengthfonction pour calculer le périmètre d'un contour.
double perimeter = cv::arcLength(contours[0], true);
Boîte englobante
Une boîte englobante est le plus petit rectangle englobant d'un contour. OpenCV fournit lacv::boundingRectfonction pour calculer la boîte englobante.
cv::Rect rect = cv::boundingRect(contours[0]);
Dessin des contours
Le dessin des contours consiste à dessiner les contours détectés sur une image. OpenCV fournit lacv::drawContoursfonction pour implémenter cela.
cv::Mat dst = cv::Mat::zeros(src.size(), CV_8UC3); cv::drawContours(dst, contours, -1, cv::Scalar(0, 255, 0), 2);
Dans le code ci-dessus,dstest l'image après le dessin des contours,cv::Scalar(0, 255, 0)est la couleur des contours,2est la largeur de ligne des contours.
Correspondance de modèle
La correspondance de modèle est une méthode permettant de trouver un modèle spécifique dans une image. OpenCV fournit lacv::matchTemplatefonction pour implémenter cela.
Correspondance de modèle simple
La correspondance de modèle unique consiste à trouver un modèle dans une image. OpenCV fournit lacv::matchTemplatefonction pour implémenter cela.
cv::Mat src = cv::imread("image.jpg");
cv::Mat templ = cv::imread("template.jpg");
cv::Mat result;
cv::matchTemplate(src, templ, result, cv::TM_CCOEFF_NORMED);
Dans le code ci-dessus,resultest la matrice de résultat de correspondance,cv::TM_CCOEFF_NORMEDest la méthode de correspondance.
Correspondance de modèles multiples
La correspondance de modèles multiples consiste à trouver plusieurs modèles dans une image. Elle peut être implémentée en parcourant la matrice de résultat de correspondance.
double minVal, maxVal; cv::Point minLoc, maxLoc; cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
Dans le code ci-dessus,maxLocest la position de la valeur maximale dans le résultat de correspondance.
Exemple
Algorithme de ligne de partage des eaux
Exemple
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// Lire l'image
Mat image = imread("objects.jpg");
if (image.empty()) {
cout << "Erreur : Impossible de charger l'image. Veuillez vérifier si le chemin est correct." << endl;
return -1;
}
// Convertir en niveaux de gris
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
// Binariser
Mat binary;
threshold(gray, binary, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);
// Supprimer le bruit
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(binary, binary, MORPH_OPEN, kernel, Point(-1, -1), 2);
// Calculer la transformée de distance
Mat dist;
distanceTransform(binary, dist, DIST_L2, 5);
// Normaliser l'image de transformée de distance
normalize(dist, dist, 0, 1.0, NORM_MINMAX);
// Binariser l'image de transformée de distance
threshold(dist, dist, 0.5, 1.0, THRESH_BINARY);
// Trouver les contours
Mat dist_8u;
dist.convertTo(dist_8u, CV_8U);
vector<vector<Point>> contours;
findContours(dist_8u, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// Créer l'image de marqueurs
Mat markers = Mat::zeros(dist.size(), CV_32S);
for (size_t i = 0; i < contours.size(); i++) {
drawContours(markers, contours, static_cast<int>(i), Scalar(static_cast<int>(i) + 1), -1);
}
// Appliquer l'algorithme watershed
watershed(image, markers);
// Afficher le résultat
Mat result = image.clone();
for (int i = 0; i < markers.lignes; i++) {
for (int j = 0; j < markers.cols; j++) {
if (markers.at<int>(i, j) == -1) {
result.at<Vec3b>(i, j) = Vec3b(0, 255, 0); // Marquer les limites en vert
}
}
}
imshow("Résultat du watershed", result);
waitKey(0);
return 0;
}
Détection de contours
La détection de contours est utilisée pour extraire les limites des objets dans une image.
OpenCV fournit la fonction findContours pour détecter les contours.
Exemple
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// Lire l'image
Mat image = imread("objects.jpg");
if (image.empty()) {
cout << "Erreur : Impossible de charger l'image. Veuillez vérifier si le chemin est correct." << endl;
return -1;
}
// Convertir en niveaux de gris
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
// Binariser
Mat binary;
threshold(gray, binary, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);
// Trouver les contours
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(binary, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
// Dessiner les contours
Mat result = Mat::zeros(image.size(), CV_8UC3);
for (size_t i = 0; i < contours.size(); i++) {
drawContours(result, contours, i, Scalar(0, 255, 0), 2);
}
// Afficher le résultat
imshow("Contours", result);
waitKey(0);
return 0;
}
Opérations morphologiques
Les opérations morphologiques sont des techniques de traitement d'image basées sur la forme, couramment utilisées pour éliminer le bruit, séparer les objets, et plus encore.
Exemple
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// Lire l'image
Mat image = imread("noisy_image.jpg");
if (image.empty()) {
cout << "Erreur : Impossible de charger l'image. Veuillez vérifier si le chemin est correct." << endl;
return -1;
}
// Convertir en niveaux de gris
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
// Binariser
Mat binary;
threshold(gray, binary, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);
// Définir le noyau
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
// Opération d'ouverture (éliminer le bruit)
Mat opened;
morphologyEx(binary, opened, MORPH_OPEN, kernel);
// Opération de fermeture (combler les trous)
Mat closed;
morphologyEx(opened, closed, MORPH_CLOSE, kernel);
// Afficher le résultat
imshow("Binaire original", binary);
imshow("Image ouverte", opened);
imshow("Image fermée", closed);
waitKey(0);
return 0;
}
Traitement d'histogramme
Le traitement d'histogramme est utilisé pour analyser la distribution des pixels d'une image. Les opérations courantes incluent l'égalisation d'histogramme, l'appariement d'histogramme, et plus encore.
Exemple
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// Lire l'image
Mat image = imread("low_contrast.jpg");
if (image.empty()) {
cout << "Erreur : Impossible de charger l'image. Veuillez vérifier si le chemin est correct." << endl;
return -1;
}
// Convertir en niveaux de gris
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
// Égalisation d'histogramme
Mat equalized;
equalizeHist(gray, equalized);
// Afficher le résultat
imshow("Image originale", gray);
imshow("Image égalisée", equalized);
waitKey(0);
return 0;
}
Correspondance de modèle
La correspondance de modèles est utilisée pour trouver des régions dans une image qui sont similaires à un modèle.
Exemple
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// Lire l'image et le modèle
Mat image = imread("scene.jpg");
Mat templ = imread("template.jpg");
if (image.empty() || templ.empty()) {
cout << "Erreur : Impossible de charger l'image. Veuillez vérifier si le chemin est correct." << endl;
return -1;
}
// Correspondance de modèles
Mat result;
matchTemplate(image, templ, result, TM_CCOEFF_NORMED);
// Trouver la meilleure position de correspondance
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc);
// Dessiner un rectangle
rectangle(image, maxLoc, Point(maxLoc.x + templ.cols, maxLoc.y + templ.rows), Scalar(0, 255, 0), 2);
// Afficher le résultat
imshow("Correspondance de modèle", image);
waitKey(0);
return 0;
}