Categories: BaseOpenCV

Sélectionner une région d’intérêt (ROI) avec OpenCV

Dans cet article, nous allons voir comment sélectionner une partie de l’image, une région d’intérêt, grâce à OpenCV. Nous allons illustrer cette fonction à travers un programme qui prend en entrée une image. L’utilisateur sélectionne avec sa souris la zone d’intérêt.Enfin, on enregistre l’image découpée.

Dans les anciennes versions d’OpenCV, il était nécessaire de créer une fonction afin de récupérer les évènements de cliques de la souris: enregistrer les coordonnées de la souris lorsque le bouton gauche de la souris était enclenché (cv2.EVENT_LBUTTONDOWN) et de nouveau quand il était relâché (cv2.EVENT_LBUTTONUP). Nous obtenions ainsi les coordonnées de la zone d’intérêt. 

Depuis la version 3.0 d’OpenCV, plus besoin de se prendre la tête, une fonction a été implémentée: cv2.selectROI. Utilisons donc cette fonction 🙂

Sélection d’une région d’intérêt

Notre fonction sera donc composée de 3 parties:

  • Lire une image.
  • Sélectionner la zone d’intérêt.
  • Afficher et enregistrer la zone d’intérêt.

Nous aurons besoin de 3 bibliothèques pour notre programme: argparse, permettant récupérer l’image en entrée de notre programme; re permettant de gérer les expressions régulières (regex) et enfin cv2

import argparse
import cv2
import re

Lecture de l’image

Nous commençons logiquement par la lecture de l’image. Cette image est fournie en argument lors de l’appel de notre programme. Nous définissons donc l’argument attendu aux lignes 5-7, c’est-à-dire le chemin de l’image, et nous la lisons ligne 8.

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Chemin de l'image")
args = vars(ap.parse_args())
img=cv2.imread(args["image"])

Ensuite, nous allons définir le nom du fichier de sortie. Nous allons reprendre le nom du fichier d’origine auquel nous allons ajouter « _crop » ainsi que l’extension « .jpg ».

Nous recherchons donc la chaine de caractère précédant un point dans le chemin fournit lors de l’appel de la fonction (l. 10). Nous ajoutons ensuite le complément du nouveau nom, ainsi l’extension (l. 11).

SI nous n’utilisions que des images avec une extension à 3 caractères (‘.jpg’, ‘.png’, ‘.bmp’, …), nous aurions pu utiliser une expression du type args[« image »][:-4]  afin de sélectionner le nom de l’image de l’extension. Cependant le résultat obtenu avec une image  ‘.tiff’ ou ‘.jpeg’, ne serait pas celui espéré: ‘test._crop.jpg’. Les regex nous permettent de pallier ce problème.

m = re.search('[^.]*',args["image"])
path=m.group(0)+'_crop.jpg'

Passons maintenant à ce qui nous intéresse: la sélection de la ROI !

Sélection de la région d’intérêt

ROI = cv2.selectROI(img)

Pour cela, rien de plus simple, il suffit d’appeler la fonction cv2.selectROI. Cette fonction prend en entrée l’image d’origine et renvoie un tuple de la forme [x,y,w,h], avec x,y les coordonnées du point supérieur gauche, w (width) la largeur et h (height) la hauteur.

De base, cette fonction vous permet de sélectionner un rectangle en partant du coin supérieur gauche vers le point inférieur droit. Si vous souhaitez sélectionner et ensuite élargir la région d’intérêt, il suffit de passer l’argument fromCenter=True  lors de l’appel de la fonction.

Lors de l’appel de la fonction cv2.selectROI deux options nous sont proposées: sélectionner une ROI et appuyer sur espace ou entrer pour valider, ou annuler le processus de sélection en appuyant sur le touche c.

Enregistrement de l’image découpée

Si l’opération est annulée, la ROI renvoyé sera (0,0,0,0), ce qui posera problème pour découper l’image d’origine. Le programme se terminera avec une erreur. Nous ajoutons donc une condition ligne 15 pour découper l’image uniquement lorsqu’une zone est définie. Nous découpons ensuite l’image ligne 16, nous l’affichons lignes 17-18. Pour finir, nous enregistrons l’image découpée ligne 19.

if ROI!=(0,0,0,0):
    imgCrop = img[int(ROI[1]):int(ROI[1]+ROI[3]), int(ROI[0]):int(ROI[0]+ROI[2])]
    cv2.imshow("Image", imgCrop)
    cv2.waitKey(0)
    cv2.imwrite(path,imgCrop)
 
cv2.destroyAllWindows()
Florent

Recent Posts

Conduite autonome : comment détecter les lignes d’une route

Détecter les voies de circulation est une étape incontournable pour la réalisation d’un système de…

2 jours ago

Capturer une image avec la caméra du Raspberry

Dans cet article, nous allons voir comment capturer simplement une image grâce au module raspicam…

4 mois ago

Détecter les repères faciaux (facial landmarks) avec Dlib

Aujourd’hui nous allons utiliser Dlib et OpenCV pour détecter les repères faciaux (facial landmarks) dans…

2 ans ago

Reconnaissance d’objets en temps réel avec MobileNet

Nous avons vu dans un précédent article comment utiliser l’algorithme MobileNetSSD pour la reconnaissance d’objet…

2 ans ago

Reconnaissance d’objet avec MobileNet et OpenCV

Dans cet article, nous nous intéressons à l’utilisation des réseaux de neurones convolutifs dans le…

2 ans ago

Où est Charlie ?

Derrière ce titre un peu trompeur, nous n’allons pas trouver Charlie dans une image, mais…

2 ans ago