Segmenter une image en k-means

en langage python

L'essentiel de cette page

Voici quelques explications pour segmenter une image avec opencv. L'installation de ce module peut être délicate, mais fera gagner beaucoup de temps de traitement.

Se référer à la page traitement d'image pour voir comment charger l'image en amont du traitement.

Il existe plusieurs méthode de k-means pour catégoriser automatiquement les points et les segmenter mais problème ! C'est en général tellement lourd que ça plante.

On pourrait très bien faire un k-means classique sur le tableau de composantes rgb de l'exemple ci-dessus (partie 2) mais la fonction de k-means a toutes les chances de planter à cause de la taille de la dataframe.

L'idéeal est d'utiliser opencv, ce module permet d'implémenter de nombreuses fonctions très rapide de traitement d'images.

1- Installer opencv (module cv2)

Taper un des codes suivant dans la console windows (il faut avoir installer PIP) :

python -m pip install --user cv2

run pip install opencv-python

On peut aussi faire une installation manuelle en suivant ces instructions :

2- Charger l'image et la convertir au format numpy

import numpy as np

import cv2

import easygui

image_ref = cv2.imread(easygui.fileopenbox())

Z = image_ref.reshape((-1,3))

# convert to np.float32

Z = np.float32(Z)

cv2.imshow("Image d'origine",image_ref)

3- Réaliser une segmentation avec la fonction k-means d'opencv

  • Appliquer le k-means

# definir : criteria, nombre de catégories (K) et faire le kmeans()

criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) # Paramétrage

K = 10

ret,label,center=cv2.kmeans(Z,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)

  • Afficher l'image segmentée

center = np.uint8(center)

resultat = center[label.flatten()]

resultat = resultat .reshape((image_ref.shape))

cv2.imshow('Résultat de la segmentation',resultat ) # Affichage avec cv 2

import matplotlib.pyplot as plt

# Reconversion pour affichage correcte

image_reconvertie=cv2.cvtColor(resultat,cv2.COLOR_BGR2RGB)

plt.imshow(image_reconvertie) ; plt.show()

# Affichage avec matplotlib.pyplot

# groupes créés

print(np.unique(label.flatten()))

Image segmentée

4- Extraire les catégories intéressantes (par exemple, les prairies)

def extraction(img,label,criteria,centers) :

for i in range(len(label)) :

if label[i] not in criteria :

label[i] = 0

criteria = set(criteria)

indices_center = set(range(len(centers)))

indices_center = indices_center-criteria

indices_center = list(indices_center)

centerss = centers.copy()

centerss[indices_center] = [0,0,0]

new_img = centerss[label]

new_img = new_img.reshape((img.shape))

return(new_img)

resultat_prairie = extraction(image_ref,label.flatten(),[0,1,2,4],center)


image_reconvertie=cv2.cvtColor(resultat_prairie,cv2.COLOR_BGR2RGB) # Reconversion pour affichage correcte

import matplotlib.pyplot as plt

plt.imshow(image_reconvertie) ; plt.show() # Affichage avec matplotlib.pyplot


#cv2.imshow('Affichage de la composante prairie des résultats',resultat_prairie)

5- Utiliser les critères de l'image précédente (d'apprentissage) pour segmenter de nouvelles images

# Ouvrir la nouvelle image

nouvelle_image = cv2.imread(easygui.fileopenbox())

Z2 = nouvelle_image.reshape((-1,3)) ; Z2 = np.float32(Z2)

criteria = (cv2.TERM_CRITERIA_MAX_ITER, 0, 0) # Paramétrage pour que l'arrêt se fasse à une itération

K = 10

ret2,label2,center2=cv2.kmeans(Z2,K,center,criteria,10,cv2.KMEANS_USE_INITIAL_LABELS)

criteria = (cv2.TERM_CRITERIA_MAX_ITER, 1, 1)

ret2,label2,center2=cv2.kmeans(Z2,K,center,criteria, 1, cv2.KMEANS_USE_INITIAL_LABELS, center)

# Conversion en image

center2 = np.uint8(center2)

sortie = center2[label2.flatten()]

sortie= sortie.reshape((nouvelle_image.shape))

plt.imshow(sortie) ; plt.show() # Résultat de la segmentation

# il ne reste qu'à copier coller la partie 3.4 pour extraire les prairies de cette nouvelle image

resultat_prairie = extraction(sortie,label2.flatten(),[0,1,2,4],center)


  • A ce stade, l'apprentissage ne semble pas bien fonctionner : center2 et center sont différents ce qui prouve que l'apprentissage n'a pas pu fixer des centres et que les prairies seront donc segmentées avec des critères variables...

A développer :

  1. Regrouper des lignes de pixel en niveau de gris et en couleur

  2. Récupérer la position d'un pixel

  3. Afficher l'image

  4. Superposer 3 images r, g, b