Étiquettes : ,

Une application intéressante en robotique est le suivi de ligne. C’est pourquoi, dans ce tutoriel nous allons implémenter un code en Python qui permettra de détecter un câble son centre. Afin de réaliser ce suivi de ligne nous allons effectuer du traitement d’image avec OpenCV.

Cela vous permettra ensuite de pouvoir réaliser votre régulation pour toujours garder le centre du câble au milieu de la caméra et donc suivre la trajectoire ! Nous avons donc décidé de réaliser ce tutoriel sur Raspberry Pi puisque ce tutoriel a pour vocation d’effectuer du traitement d’image pour un robot en utilisant la Pi Caméra.

Matériel

Mise en place

Code

Pour commencer, afin que vous puissiez réutiliser la détection d’une ligne ou d’un câble sur une vidéo (succession d’images), nous allons implémenter une Classe. Cette classe prendra en paramètre le chemin de l’image. Par défaut si l’image se trouve dans le même dossier que le code il suffira de mettre le nom de l’image, par exemple : « cam.jpg »).

Ensuite, enregistrer le code python ci-dessous dans un fichier nommé : suivi_ligne.py

# -*- coding: utf-8 -*-
"""
@author: AranaCorp
"""
import cv2 
import time
import numpy as np
import matplotlib.pyplot as plt


class LineTracking():
    """
    Classe permettant le traitement d'image, la délimitation d'un contour et permet de trouver le centre de la
    forme detectée
    """
    def __init__(self,img_file):
        """The constructor."""
        self.img = cv2.imread(img_file)
        self.img_final = self.img
        self.cendroids = []
        self.mean_centroids = [0,0]
        
    def processing(self):
        """Méthode permettant le traitement d'image"""
        self.img=cv2.resize(self.img,(int(self.img.shape[1]*0.2),int(self.img.shape[0]*0.2))) #redimensionner l'image d'origine
        print(img.shape)
        self.img = self.img[199:391, 149:505] #on recentre l'image en excluant les zones extérieures afin d'avoir une plus grande précision pour la suite
        gray = cv2.cvtColor(self.img, cv2.COLOR_BGR2GRAY) #on passe l'image en nuances de gris
        blur = cv2.GaussianBlur(gray,(5,5),0) #on floute l'image
        ret,thresh = cv2.threshold(blur,60,255,cv2.THRESH_BINARY_INV) #on binarise l'image

        """Une ouverture permet d'enlever tous les élements qui sont plus petits que l'élement structurant (ou motif)
        Une fermeture permet de "combler" les trous qui ont une taille inférieur à l'élement structurant """
        kernel_open = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)) #on créé l'élement structurant de l'ouverture
        kernel_close = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(10,10)) #on créé l'élement structurant de la fermeture
        
        thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel_open) #on fait une ouverture suivant un motif
        thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel_close) #on fait une fermeturesuivant un motif

        connectivity = 8  

        output = cv2.connectedComponentsWithStats(thresh, connectivity, cv2.CV_32S) #permet de délimiter une forme
        num_labels = output[0]
        labels = output[1]
        stats = output[2]
        self.centroids = output[3] #donne les centres de la ou des formes de l'image
        
        for c in self.centroids :
            """Permet de faire la moyenne des centres de la forme, en effet sur l'image test,
               il y a deux centres qui sont très proches et la moyenne de deux convient.
               On pourra imaginer que dans un cas général on modifie cela
            """
            self.mean_centroids[0] += c[0]/len(self.centroids)
            self.mean_centroids[1] += c[1]/len(self.centroids)

        self.img_final = cv2.cvtColor(thresh, cv2.COLOR_GRAY2BGR)
        
        #permet de rajouter un carré rouge à l'endroit du centre de la forme
        self.img_final[int(self.mean_centroids[1])-1 : int(self.mean_centroids[1])+2, int(self.mean_centroids[0])-1 : int(self.mean_centroids[0])+2] = [0,0,255] 

Enfin, créez un nouveau script python, par exemple : test_tracking.py

# -*- coding: utf-8 -*-
"""
@author: Antonin Lizé
"""
import cv2
from suivi_ligne import LineTracking

if __name__ == '__main__' :
    test = LineTracking('cam.jpg') #créer un objet LineTracking qui est la Classe créée au dessus
    test.processing() #lance le traitement d'image
    while True :
        cv2.imshow('image',test.img) #affiche l'image original après redimensionnement
        cv2.imshow('cable',test.img_final) #affiche l'image après traitement
        key= cv2.waitKey(1);
        if  key == ord(' '): #pour fermer les fenêtres appuyer sur la barre 'espace'
            break
    cv2.destroyAllWindows()
    

Vous avez maintenant tous les codes pour tester votre traitement d’image. Lancez dans un terminal la commande :

python3 test_tracking.py

Pour stopper l’affichage appuyer sur la barre « espace ».

Pour conclure, le traitement d’image vient d’être effectué sur une image. Vous pouvez maintenant l’implémenter dans une boucle de traitement pour une vidéo.

Application

Vous pouvez maintenant utilisez la classe LineTracking dans votre fichier principal qui ouvre la caméra de la Raspberry. Pour plus d’informations sur l’installation d’une PiCam sur Raspberry Pi vous pouvez suivre notre tutoriel : https://www.aranacorp.com/fr/gerer-une-picam-v2-avec-raspberry-pi/

Source