Una aplicación interesante en robótica es el reconocimiento de patrones. En este tutorial vamos a utilizar la librería OpenCV en un código Python que nos permitirá detectar el centro de un cable. Para lograr este seguimiento de la línea haremos un poco de procesamiento de imágenes con OpenCV.
¡Esto le permitirá entonces hacer su regulación para mantener siempre el centro del cable en el centro de la cámara y así seguir la trayectoria! Decidimos hacer este tutorial en Raspberry Pi ya que este tutorial es sobre el procesamiento de imágenes para un robot utilizando la cámara Pi.
Material
- Una Raspberry Pi (o un ordenador)
- Un monitor, un teclado y un ratón o un control remoto a través de VNC
Configuración
- Instalación de OpenCV en Raspberry Pi
- Una foto de un cable o línea negra (por defecto descarga la foto de abajo para trabajar en el mismo ejemplo, fue tomada con la cámara Pi)
Código
Para empezar, para poder reutilizar la detección de una línea o un cable en un vídeo (sucesión de imágenes), implementaremos una Clase. Esta clase tomará como parámetro la ruta de la imagen. Por defecto, si la imagen está en la misma carpeta que el código, bastará con poner el nombre de la imagen, por ejemplo: «cam.jpg»).
A continuación, guarde el código python siguiente en un archivo llamado: 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_inter = self.img 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(self.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 self.img_inter=thresh """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])-10 : int(self.mean_centroids[1])+20, int(self.mean_centroids[0])-10 : int(self.mean_centroids[0])+20] = [0,0,255] for c in self.centroids : self.img_final[int(c[1])-5 : int(c[1])+10, int(c[0])-5 : int(c[0])+10] = [0,255,0]
Por último, cree un nuevo script python, por ejemplo: test_tracking.py
if __name__ == '__main__' : test = LineTracking('cam.png') #créer un objet LineTracking qui est la Classe créée au dessus .png ou .jpg test.processing() #lance le traitement d'image while True : cv2.imshow('image',test.img) #affiche l'image original après redimensionnement #cv2.imshow('process',test.img_inter ) #affiche l'image après traitement 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()
Ahora tiene todos los códigos para probar el procesamiento de imágenes. Ejecute el comando :
python3 test_tracking.py
Resultado
Se abren dos ventanas con la imagen original y la imagen procesada. Puedes ver que un cuadrado verde marca la posición del cable. Este punto puede utilizarse para dirigir un robot o una cámara móvil.
Para detener la visualización, pulse la barra espaciadora.
Para terminar, el tratamiento se acaba de hacer sobre una imagen. Ahora puedes implementarlo en un bucle de procesamiento para un vídeo.
Aplicaciones
Ahora puedes usar la clase LineTracking en tu archivo principal que abre la cámara de la Raspberry. Para más información sobre cómo instalar una PiCam en una Raspberry Pi puedes seguir nuestro tutorial