Segmentation d'image dans OpenCV

Manav Narula 30 janvier 2023
  1. Segmentation d’image à l’aide de opencv en Python
  2. Utiliser l’algorithme GrabCut pour la segmentation d’images à l’aide de opencv
  3. Utiliser la détection des couleurs pour la segmentation d’image à l’aide de opencv
  4. Conclusion
Segmentation d'image dans OpenCV

Le traitement d’image est une étape cruciale dans les tâches de vision par ordinateur. En Python, nous pouvons utiliser la bibliothèque opencv pour implémenter plusieurs techniques de traitement d’images utilisant différents objets et méthodes.

Ce didacticiel montrera comment effectuer une segmentation d’image à l’aide de opencv en Python.

Segmentation d’image à l’aide de opencv en Python

La segmentation d’image fait référence au processus de division d’une image donnée en plusieurs parties.

Nous ajoutons des courbes qui joignent les points le long de la limite des parties segmentées. Ces courbes sont appelées contours.

La segmentation d’image est très utile en vision par ordinateur et a de nombreuses applications réelles. Nous pouvons utiliser cette technique pour segmenter des parties d’une image afin de classer divers objets.

Plusieurs méthodes disponibles peuvent être utilisées pour la segmentation d’images en utilisant opencv en Python.

La principale méthode qui diffère dans chaque technique de segmentation d’image est généralement basée sur le critère de l’image segmentée. Nous pouvons avoir une segmentation d’image basée sur la détection de certaines couleurs, des algorithmes prédéfinis comme l’algorithme Watershed, la détection des bords et même la sélection des parties segmentées en fonction des entrées de l’utilisateur.

Nous aborderons certaines de ces méthodes dans les sections suivantes.

Utiliser l’algorithme GrabCut pour la segmentation d’images à l’aide de opencv

Cette méthode nécessite une interaction de l’utilisateur avec la souris et le clavier. La bibliothèque opencv intégrée contient des objets et des méthodes qui peuvent lire les entrées de l’utilisateur à partir de la souris et du clavier.

L’algorithme GrabCut est un outil très simple et utile pour la segmentation d’images. Dans cette technique, nous utilisons l’entrée de l’utilisateur pour sélectionner une région d’une image donnée.

Cet algorithme détecte automatiquement le premier plan et l’arrière-plan de la partie segmentée, et nous pouvons les afficher.

Nous pouvons utiliser la fonction grabCut() de la bibliothèque opencv pour implémenter cet algorithme. Nous transmettrons l’image avec la case de la région sélectionnée dans cette fonction pour la segmentation de l’image.

Voir le code suivant pour un exemple.

import cv2
import numpy as np


def algo_grabcut(img, bounding_box):
    seg = np.zeros(img.shape[:2], np.uint8)
    x, y, width, height = bounding_box
    seg[y : y + height, x : x + width] = 1
    background_mdl = np.zeros((1, 65), np.float64)
    foreground_mdl = np.zeros((1, 65), np.float64)

    cv2.grabCut(
        img, seg, bounding_box, background_mdl, foreground_mdl, 5, cv2.GC_INIT_WITH_RECT
    )

    mask_new = np.where((seg == 2) | (seg == 0), 0, 1).astype("uint8")
    img = img * mask_new[:, :, np.newaxis]
    cv2.imshow("Output", img)


def box_draw(click, x, y, flag_param, parameters):
    global x_pt, y_pt, drawing, topleft_pt, bottomright_pt, img

    if click == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        x_pt, y_pt = x, y

    elif click == cv2.EVENT_MOUSEMOVE:
        if drawing:
            topleft_pt, bottomright_pt = (x_pt, y_pt), (x, y)
            image[y_pt:y, x_pt:x] = 255 - img[y_pt:y, x_pt:x]
            cv2.rectangle(image, topleft_pt, bottomright_pt, (0, 255, 0), 2)

    elif click == cv2.EVENT_LBUTTONUP:
        drawing = False
        topleft_pt, bottomright_pt = (x_pt, y_pt), (x, y)
        image[y_pt:y, x_pt:x] = 255 - image[y_pt:y, x_pt:x]
        cv2.rectangle(image, topleft_pt, bottomright_pt, (0, 255, 0), 2)
        bounding_box = (x_pt, y_pt, x - x_pt, y - y_pt)

        algo_grabcut(img, bounding_box)


drawing = False
topleft_pt, bottomright_pt = (-1, -1), (-1, -1)

img = cv2.imread("img4.jpg")
img = cv2.resize(img, (500, 500))
image = img.copy()
cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", box_draw)

while True:
    cv2.imshow("Frame", image)
    ch = cv2.waitKey(1)
    if ch == 32:
        break

cv2.destroyAllWindows()

Production:

région sélectionnée de l’algorithme de grabcut

Image segmentée à l’aide de l’algorithme GrabCut

Comprenons ce qui se passe dans l’exemple ci-dessus.

La fonction box_draw() lit l’interaction de l’utilisateur avec la souris pour sélectionner la région de segmentation de l’image. La boîte et l’image sont passées à la fonction algo_grabcut() qui prend l’image et crée le masque binaire pour l’image segmentée.

Nous utilisons ce masque et affichons le premier plan de la partie segmentée.

Utiliser la détection des couleurs pour la segmentation d’image à l’aide de opencv

En Python, on peut utiliser le opencv pour la détection des couleurs. Il existe différents espaces colorimétriques disponibles pour qu’une image représente ses couleurs.

Dans notre cas, nous utiliserons l’espace colorimétrique HSV pour déterminer les plages de la couleur donnée.

Nous utiliserons différentes couleurs pour la segmentation des images. Nous créons une gamme pour une couleur donnée et utilisons la fonction inRange() de la bibliothèque opencv pour détecter les objets qui correspondent à cette couleur.

Cela renvoie un masque binaire. On affine ensuite ce masque et on ajoute des contours à cette partie détectée.

Comme indiqué précédemment, les contours sont les courbes sur les limites de la partie segmentée. Nous allons utiliser la fonction findContours() pour trouver les bordures à l’aide du masque créé puis dessiner ces contours avec la fonction drawContours().

Voir le code ci-dessous.

import cv2
import numpy as np

img = cv2.imread("img4.jpg")
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
bound_lower = np.array([36, 25, 25])
bound_upper = np.array([70, 255, 255])

mask_green = cv2.inRange(hsv_img, bound_lower, bound_upper)
kernel = np.ones((7, 7), np.uint8)

mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_CLOSE, kernel)
mask_green = cv2.morphologyEx(mask_green, cv2.MORPH_OPEN, kernel)

seg_img = cv2.bitwise_and(img, img, mask=mask_green)
contours, hier = cv2.findContours(
    mask_green.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE
)
output = cv2.drawContours(seg_img, contours, -1, (0, 0, 255), 3)

cv2.imshow("Result", seg_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Production:

Segmentation d’image à l’aide de la détection de couleur

Dans le code ci-dessus, nous segmentons les objets verts d’une image donnée. Tout d’abord, nous convertissons l’image dans l’espace colorimétrique HSV à l’aide de la fonction cvtColor.

Ensuite, nous procédons à la création du masque qui stocke la couleur détectée. Nous supprimons également tout bruit indésirable de ce masque.

Ensuite, nous dessinons les contours du segment détecté et l’affichons. La fonction waitKey() empêche la fermeture automatique de la fenêtre d’image.

Il attend que l’utilisateur appuie sur une touche puis la ferme.

Conclusion

Dans ce didacticiel, nous avons abordé la segmentation d’images à l’aide de la bibliothèque opencv de Python. Nous avons également mis en place quelques techniques pour cela, bien que beaucoup d’autres soient possibles.

Nous avons discuté des bases de la segmentation d’image et de l’approche et du résultat final dans chaque méthode.

Nous avons discuté en détail de deux méthodes. Dans un premier temps, nous avons implémenté l’algorithme GrabCut.

Dans cet algorithme, l’utilisateur sélectionne une région qu’il souhaite utiliser pour la segmentation. A partir de cette portion, nous détectons les objets de premier plan et les affichons.

Dans la deuxième technique, nous avons utilisé la détection de couleur. Nous avons détecté des objets de couleur verte.

Dans ce type de segmentation, nous convertissons l’image dans l’espace colorimétrique donné et utilisons les gammes de couleurs de ce modèle pour détecter les couleurs à l’aide de la fonction inRange(). Nous utilisons ce masque pour segmenter l’image et tracer des contours autour des bords.

Auteur: Manav Narula
Manav Narula avatar Manav Narula avatar

Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.

LinkedIn