Maison > développement back-end > Tutoriel Python > [Segmentation Python-CVImage : méthodes Canny Edges, Watershed et K-Means

[Segmentation Python-CVImage : méthodes Canny Edges, Watershed et K-Means

Patricia Arquette
Libérer: 2024-12-11 05:33:09
original
887 Les gens l'ont consulté

La segmentation est une technique fondamentale de l'analyse d'image qui nous permet de diviser une image en parties significatives basées sur des objets, des formes ou des couleurs. Il joue un rôle central dans des applications telles que la détection d’objets, la vision par ordinateur et même la manipulation artistique d’images. Mais comment parvenir à une segmentation efficace ? Heureusement, OpenCV (cv2) propose plusieurs méthodes de segmentation conviviales et puissantes.

Dans ce didacticiel, nous explorerons trois techniques de segmentation populaires :

  • Canny Edge Detection – parfait pour tracer des objets.
  • Algorithme de bassin versant – idéal pour séparer les régions qui se chevauchent.
  • Segmentation des couleurs K-Means – idéale pour regrouper des couleurs similaires dans une image.

Pour rendre ce didacticiel attrayant et pratique, nous utiliserons des images satellite et aériennes d'Osaka, au Japon, en nous concentrant sur les anciens tumulus kofun. Vous pouvez télécharger ces images et l'exemple de bloc-notes correspondant à partir de la page GitHub du didacticiel.

Détection Canny Edge à la segmentation des contours

Canny Edge Detection est une méthode simple mais puissante pour identifier les bords d'une image. Il fonctionne en détectant les zones de changement rapide d’intensité, qui sont souvent les limites des objets. Cette technique génère des contours « à bords fins » en appliquant des seuils d'intensité. Plongeons dans sa mise en œuvre à l'aide d'OpenCV.

Exemple : Détection des contours dans une image satellite
Ici, nous utilisons une image satellite d'Osaka, en particulier un tumulus kofun, comme cas de test.

import cv2 
import numpy as np
import matplotlib.pyplot as plt
files = sorted(glob("SAT*.png")) #Get png files 
print(len(files))
img=cv2.imread(files[0])
use_image= img[0:600,700:1300]
gray = cv2.cvtColor(use_image, cv2.COLOR_BGR2GRAY)

#Stadard values 
min_val = 100
max_val = 200
# Apply Canny Edge Detection
edges = cv2.Canny(gray, min_val, max_val)
#edges = cv2.Canny(gray, min_val, max_val,apertureSize=5,L2gradient = True )
False
# Show the result
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(cv2.cvtColor(use_image, cv2.COLOR_BGR2RGB))
plt.title('Original Image'), plt.axis('off')
plt.subplot(132), plt.imshow(gray, cmap='gray')
plt.title('Grayscale Image'), plt.axis('off')
plt.subplot(133), plt.imshow(edges, cmap='gray')
plt.title('Canny Edges'), plt.axis('off')
plt.show()

Copier après la connexion
Copier après la connexion
Copier après la connexion

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods

Les bords de sortie délimitent clairement des parties du tumulus funéraire de Kofun et d'autres régions d'intérêt. Cependant, certaines zones sont omises en raison du seuillage strict. Les résultats dépendent fortement du choix de min_val et max_val, ainsi que de la qualité de l'image.

Pour améliorer la détection des contours, nous pouvons prétraiter l'image pour répartir les intensités de pixels et réduire le bruit. Ceci peut être réalisé en utilisant l'égalisation d'histogramme (cv2.equalizeHist()) et le flou gaussien (cv2.GaussianBlur()).

use_image= img[0:600,700:1300]
gray = cv2.cvtColor(use_image, cv2.COLOR_BGR2GRAY)
gray_og = gray.copy()
gray = cv2.equalizeHist(gray)
gray = cv2.GaussianBlur(gray, (9, 9),1)

plt.figure(figsize=(15, 5))
plt.subplot(121), plt.imshow(gray, cmap='gray')
plt.title('Grayscale Image')
plt.subplot(122)
_= plt.hist(gray.ravel(), 256, [0,256],label="Equalized") 
_ = plt.hist(gray_og.ravel(), 256, [0,256],label="Original",histtype='step')
plt.legend()
plt.title('Grayscale Histogram')

Copier après la connexion
Copier après la connexion
Copier après la connexion

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods

Ce prétraitement uniformise la répartition de l'intensité et lisse l'image, ce qui aide l'algorithme de détection des bords de Canny à capturer des bords plus significatifs.

Les bords sont utiles, mais ils indiquent uniquement les limites. Pour segmenter les zones fermées, nous convertissons les bords en contours et les visualisons.

# Edges to contours 
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Calculate contour areas
areas = [cv2.contourArea(contour) for contour in contours]

# Normalize areas for the colormap
normalized_areas = np.array(areas)
if normalized_areas.max() > 0:
    normalized_areas = normalized_areas / normalized_areas.max()

# Create a colormap
cmap = plt.cm.jet

# Plot the contours with the color map
plt.figure(figsize=(10, 10))
plt.subplot(1,2,1)
plt.imshow(gray, cmap='gray', alpha=0.5)  # Display the grayscale image in the background
mask = np.zeros_like(use_image)
for contour, norm_area in zip(contours, normalized_areas):
    color = cmap(norm_area)  # Map the normalized area to a color
    color = [int(c*255) for c in color[:3]]
    cv2.drawContours(mask, [contour], -1, color,-1 )  # Draw contours on the image

plt.subplot(1,2,2)
Copier après la connexion
Copier après la connexion
Copier après la connexion

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods

La méthode ci-dessus met en évidence les contours détectés avec des couleurs représentant leurs zones relatives. Cette visualisation permet de vérifier si les contours forment des corps fermés ou simplement des lignes. Cependant, dans cet exemple, de nombreux contours restent des polygones non fermés. Un prétraitement supplémentaire ou un réglage des paramètres pourraient résoudre ces limitations.

En combinant le prétraitement et l'analyse des contours, Canny Edge Detection devient un outil puissant pour identifier les limites des objets dans les images. Cependant, cela fonctionne mieux lorsque les objets sont bien définis et que le bruit est minime. Ensuite, nous explorerons le clustering K-Means pour segmenter l'image par couleur, offrant une perspective différente sur les mêmes données.

Regroupement KMean

Le clustering K-Means est une méthode populaire en science des données pour regrouper des éléments similaires en clusters, et elle est particulièrement efficace pour segmenter des images en fonction de la similarité des couleurs. La fonction cv2.kmeans d'OpenCV simplifie ce processus, le rendant accessible pour des tâches telles que la segmentation d'objets, la suppression de l'arrière-plan ou l'analyse visuelle.

Dans cette section, nous utiliserons le clustering K-Means pour segmenter l'image du tumulus funéraire kofun en régions de couleurs similaires.

Pour commencer, nous appliquons le clustering K-Means sur les valeurs RVB de l'image, en traitant chaque pixel comme un point de données.

import cv2 
import numpy as np
import matplotlib.pyplot as plt
files = sorted(glob("SAT*.png")) #Get png files 
print(len(files))
img=cv2.imread(files[0])
use_image= img[0:600,700:1300]
gray = cv2.cvtColor(use_image, cv2.COLOR_BGR2GRAY)

#Stadard values 
min_val = 100
max_val = 200
# Apply Canny Edge Detection
edges = cv2.Canny(gray, min_val, max_val)
#edges = cv2.Canny(gray, min_val, max_val,apertureSize=5,L2gradient = True )
False
# Show the result
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(cv2.cvtColor(use_image, cv2.COLOR_BGR2RGB))
plt.title('Original Image'), plt.axis('off')
plt.subplot(132), plt.imshow(gray, cmap='gray')
plt.title('Grayscale Image'), plt.axis('off')
plt.subplot(133), plt.imshow(edges, cmap='gray')
plt.title('Canny Edges'), plt.axis('off')
plt.show()

Copier après la connexion
Copier après la connexion
Copier après la connexion

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods

Dans l'image segmentée, le tumulus et les régions environnantes sont regroupés en couleurs distinctes. Cependant, le bruit et les petites variations de couleur conduisent à des clusters fragmentés, ce qui peut rendre l'interprétation difficile.

Pour réduire le bruit et créer des clusters plus fluides, nous pouvons appliquer un flou médian avant d'exécuter K-Means.

use_image= img[0:600,700:1300]
gray = cv2.cvtColor(use_image, cv2.COLOR_BGR2GRAY)
gray_og = gray.copy()
gray = cv2.equalizeHist(gray)
gray = cv2.GaussianBlur(gray, (9, 9),1)

plt.figure(figsize=(15, 5))
plt.subplot(121), plt.imshow(gray, cmap='gray')
plt.title('Grayscale Image')
plt.subplot(122)
_= plt.hist(gray.ravel(), 256, [0,256],label="Equalized") 
_ = plt.hist(gray_og.ravel(), 256, [0,256],label="Original",histtype='step')
plt.legend()
plt.title('Grayscale Histogram')

Copier après la connexion
Copier après la connexion
Copier après la connexion

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods

L'image floue donne lieu à des clusters plus lisses, réduisant le bruit et rendant les régions segmentées plus cohérentes visuellement.

Pour mieux comprendre les résultats de la segmentation, nous pouvons créer une carte des couleurs des couleurs de cluster uniques, en utilisant matplotlib plt.fill_between;

# Edges to contours 
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Calculate contour areas
areas = [cv2.contourArea(contour) for contour in contours]

# Normalize areas for the colormap
normalized_areas = np.array(areas)
if normalized_areas.max() > 0:
    normalized_areas = normalized_areas / normalized_areas.max()

# Create a colormap
cmap = plt.cm.jet

# Plot the contours with the color map
plt.figure(figsize=(10, 10))
plt.subplot(1,2,1)
plt.imshow(gray, cmap='gray', alpha=0.5)  # Display the grayscale image in the background
mask = np.zeros_like(use_image)
for contour, norm_area in zip(contours, normalized_areas):
    color = cmap(norm_area)  # Map the normalized area to a color
    color = [int(c*255) for c in color[:3]]
    cv2.drawContours(mask, [contour], -1, color,-1 )  # Draw contours on the image

plt.subplot(1,2,2)
Copier après la connexion
Copier après la connexion
Copier après la connexion

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods

Cette visualisation donne un aperçu des couleurs dominantes de l'image et de leurs valeurs RVB correspondantes, ce qui peut être utile pour une analyse plus approfondie. COMME nous pourrions masquer et sélectionner la zone de mon code couleur maintenant.

Le nombre de clusters (K) impacte significativement les résultats. L'augmentation de K crée une segmentation plus détaillée, tandis que des valeurs inférieures produisent des regroupements plus larges. Pour expérimenter, nous pouvons parcourir plusieurs valeurs K.

import cv2 
import numpy as np
import matplotlib.pyplot as plt
files = sorted(glob("SAT*.png")) #Get png files 
print(len(files))
img=cv2.imread(files[0])
use_image= img[0:600,700:1300]
gray = cv2.cvtColor(use_image, cv2.COLOR_BGR2GRAY)

#Stadard values 
min_val = 100
max_val = 200
# Apply Canny Edge Detection
edges = cv2.Canny(gray, min_val, max_val)
#edges = cv2.Canny(gray, min_val, max_val,apertureSize=5,L2gradient = True )
False
# Show the result
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(cv2.cvtColor(use_image, cv2.COLOR_BGR2RGB))
plt.title('Original Image'), plt.axis('off')
plt.subplot(132), plt.imshow(gray, cmap='gray')
plt.title('Grayscale Image'), plt.axis('off')
plt.subplot(133), plt.imshow(edges, cmap='gray')
plt.title('Canny Edges'), plt.axis('off')
plt.show()

Copier après la connexion
Copier après la connexion
Copier après la connexion

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods

Les résultats de regroupement pour différentes valeurs de K révèlent un compromis entre détail et simplicité :

・Valeurs K inférieures (par exemple, 2-3) : clusters larges avec des distinctions claires, adaptés à une segmentation de haut niveau.
・ Valeurs K plus élevées (par exemple, 12-15) : segmentation plus détaillée, mais au prix d'une complexité accrue et d'une potentielle sur-segmentation.

K-Means Clustering est une technique puissante pour segmenter des images en fonction de la similarité des couleurs. Avec les bonnes étapes de prétraitement, il produit des régions claires et significatives. Cependant, ses performances dépendent du choix de K, de la qualité de l’image d’entrée et du prétraitement appliqué. Nous explorerons ensuite l'algorithme de bassin versant, qui utilise des caractéristiques topographiques pour réaliser une segmentation précise des objets et des régions.

Segmentation des bassins versants

L'algorithme des bassins versants s'inspire des cartes topographiques, où les bassins versants divisent les bassins versants. Cette méthode traite les valeurs d'intensité des niveaux de gris comme une élévation, créant ainsi des « pics » et des « vallées ». En identifiant les régions d’intérêt, l’algorithme peut segmenter les objets avec des limites précises. Il est particulièrement utile pour séparer les objets qui se chevauchent, ce qui en fait un excellent choix pour les scénarios complexes tels que la segmentation cellulaire, la détection d'objets et la distinction de fonctionnalités densément regroupées.

La première étape consiste à prétraiter l'image pour améliorer les caractéristiques, suivie de l'application de l'algorithme de bassin versant.

use_image= img[0:600,700:1300]
gray = cv2.cvtColor(use_image, cv2.COLOR_BGR2GRAY)
gray_og = gray.copy()
gray = cv2.equalizeHist(gray)
gray = cv2.GaussianBlur(gray, (9, 9),1)

plt.figure(figsize=(15, 5))
plt.subplot(121), plt.imshow(gray, cmap='gray')
plt.title('Grayscale Image')
plt.subplot(122)
_= plt.hist(gray.ravel(), 256, [0,256],label="Equalized") 
_ = plt.hist(gray_og.ravel(), 256, [0,256],label="Original",histtype='step')
plt.legend()
plt.title('Grayscale Histogram')

Copier après la connexion
Copier après la connexion
Copier après la connexion

Les régions et les limites segmentées peuvent être visualisées aux côtés des étapes de traitement intermédiaires.

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods

# Edges to contours 
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Calculate contour areas
areas = [cv2.contourArea(contour) for contour in contours]

# Normalize areas for the colormap
normalized_areas = np.array(areas)
if normalized_areas.max() > 0:
    normalized_areas = normalized_areas / normalized_areas.max()

# Create a colormap
cmap = plt.cm.jet

# Plot the contours with the color map
plt.figure(figsize=(10, 10))
plt.subplot(1,2,1)
plt.imshow(gray, cmap='gray', alpha=0.5)  # Display the grayscale image in the background
mask = np.zeros_like(use_image)
for contour, norm_area in zip(contours, normalized_areas):
    color = cmap(norm_area)  # Map the normalized area to a color
    color = [int(c*255) for c in color[:3]]
    cv2.drawContours(mask, [contour], -1, color,-1 )  # Draw contours on the image

plt.subplot(1,2,2)
Copier après la connexion
Copier après la connexion
Copier après la connexion

L'algorithme identifie avec succès des régions distinctes et trace des limites claires autour des objets. Dans cet exemple, le tumulus kofun est segmenté avec précision. Cependant, les performances de l'algorithme dépendent fortement des étapes de prétraitement telles que le seuillage, la suppression du bruit et les opérations morphologiques.

L'ajout d'un prétraitement avancé, tel que l'égalisation de l'histogramme ou le flou adaptatif, peut encore améliorer les résultats. Par exemple :

# Kmean color segmentation
use_image= img[0:600,700:1300]
#use_image = cv2.medianBlur(use_image, 15)


 # Reshape image for k-means
pixel_values = use_image.reshape((-1, 3)) if len(use_image.shape) == 3 else use_image.reshape((-1, 1))
pixel_values = np.float32(pixel_values)

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
K = 3
attempts=10
ret,label,center=cv2.kmeans(pixel_values,K,None,criteria,attempts,cv2.KMEANS_PP_CENTERS)

centers = np.uint8(center)
segmented_data = centers[label.flatten()]
segmented_image = segmented_data.reshape(use_image.shape)

plt.figure(figsize=(10, 6))
plt.subplot(1,2,1),plt.imshow(use_image[:,:,::-1])
plt.title("RGB View")
plt.subplot(1,2,2),plt.imshow(segmented_image[:,:,[2,1,0]])
plt.title(f"Kmean Segmented Image K={K}")

Copier après la connexion

[Python-CVImage Segmentation : Canny Edges, Watershed, and K-Means Methods
Grâce à ces ajustements, davantage de régions peuvent être segmentées avec précision et les artefacts de bruit peuvent être minimisés.

L'algorithme de bassin versant excelle dans les scénarios nécessitant une délimitation précise des limites et une séparation des objets qui se chevauchent. En tirant parti des techniques de prétraitement, il peut gérer efficacement même des images complexes comme la région du tumulus funéraire de Kofun. Cependant, son succès dépend d'un réglage minutieux des paramètres et d'un prétraitement.

Conclusion

La segmentation est un outil essentiel dans l'analyse d'images, fournissant un moyen d'isoler et de comprendre des éléments distincts au sein d'une image. Ce didacticiel a démontré trois techniques de segmentation puissantes : Canny Edge Detection, K-Means Clustering et Watershed Algorithm, chacune étant adaptée à des applications spécifiques. De la description des anciens tumulus kofun à Osaka au regroupement de paysages urbains et à la séparation de régions distinctes, ces méthodes mettent en évidence la polyvalence d'OpenCV pour relever les défis du monde réel.

Maintenant, allez appliquer une partie de cette méthode à une application de votre choix, commentez et partagez les résultats. Aussi, si vous connaissez d'autres méthodes de segmentation simples, partagez-les également

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal