Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Suivi automatique des objets de vision

Un dispositif d'asservissement panoramique/inclinaison aidant un caméra pour suivre automatiquement les objets de couleur à l'aide de la vision.

Histoire

Présentation

Dans mon dernier tutoriel, nous avons exploré comment contrôler un périphérique Pan/Tilt Servo afin de positionner une PiCam. Nous allons maintenant utiliser notre appareil pour aider la caméra à suivre automatiquement les objets de couleur

C'est ma première expérience avec OpenCV et je dois avouer que je suis amoureux de cette fantastique "Open Source Computer Vision Library".

OpenCV est gratuit pour un usage académique et commercial. Il possède des interfaces C++, C, Python et Java et prend en charge Windows, Linux, Mac OS, iOS et Android. Dans ma série de tutoriels OpenCV, nous nous concentrerons sur Raspberry Pi (donc, Raspbian comme OS) et Python. OpenCV a été conçu pour l'efficacité de calcul et avec un fort accent sur les applications en temps réel. C'est donc parfait pour les projets d'informatique physique !

Étape 1 : BOM - Nomenclature

Parties principales :

(*) vous pouvez acheter une plate-forme Pan/Tilt complète avec les servos ou créer la vôtre.

Étape 2 :Installation du package OpenCV 3

J'utilise un Raspberry Pi V3 mis à jour vers la dernière version de Raspbian (Stretch), donc la meilleure façon d'installer OpenCV est de suivre l'excellent tutoriel développé par Adrian Rosebrock : Raspbian Stretch :Installer OpenCV 3 + Python sur votre Raspberry Pi.

J'ai essayé plusieurs guides différents pour installer OpenCV sur mon Pi. Le tutoriel d'Adrian est le meilleur. Je vous conseille de faire de même, en suivant pas à pas sa directive.

Une fois que vous avez terminé le tutoriel d'Adrian, vous devriez avoir un environnement virtuel OpenCV prêt à exécuter nos expériences sur votre Pi.

Allons dans notre environnement virtuel et vérifions qu'OpenCV 3 est correctement installé.

Adrian recommande d'exécuter la commande « source » à chaque fois que vous ouvrez un nouveau terminal pour vous assurer que vos variables système ont été correctement configurées.

source ~/.profile

Entrons ensuite dans notre environnement virtuel :

cv workon

Si vous voyez le texte (cv) précédant votre invite, alors vous êtes dans le cv virtuel environnement :

(cv) pi@raspberry:~$

Adrian attire l'attention sur le fait que l'environnement virtuel cv Python est entièrement indépendant et séquestré de la version Python par défaut incluse dans le téléchargement de Raspbian Stretch. Ainsi, les packages Python du répertoire global site-packages ne seront pas disponibles pour l'environnement virtuel cv. De même, tous les packages Python installés dans les packages de site de cv ne seront pas disponibles pour l'installation globale de Python.

Maintenant, entrez dans votre interpréteur Python :

python

et confirmez que vous utilisez la version 3.5 (ou supérieure)

Dans l'interpréteur (le « >>> » apparaîtra), importez la bibliothèque OpenCV :

importer cv2

Si aucun message d'erreur n'apparaît, l'OpenCV est correctement installé SUR VOTRE ENVIRONNEMENT VIRTUEL PYTHON.

Vous pouvez également vérifier la version d'OpenCV installée :

cv2.__version__

La 3.3.0 devrait apparaître (ou une version supérieure qui pourrait sortir dans le futur). Le Terminal PrintScreen ci-dessus montre les étapes précédentes.

Étape 3 : tester votre appareil photo

Une fois OpenCV installé dans votre RPi, testons si votre appareil photo fonctionne correctement.

Je suppose que vous avez déjà installé une PiCam sur votre Raspberry Pi.

Entrez le code Python ci-dessous sur votre IDE :

importer numpy en tant que npimport cv2cap =cv2.VideoCapture(0)while(True):ret, frame =cap.read() frame =cv2.flip(frame, -1) # Retourner la caméra verticalement gray =cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow('frame', frame) cv2.imshow('gray', gray) if cv2.waitKey(1) &0xFF ==ord('q'):breakcap.release()cv2.destroyAllWindows()

Le code ci-dessus capturera le flux vidéo qui sera généré par votre PiCam, l'affichant à la fois en couleur BGR et en mode gris.

Notez que j'ai fait pivoter mon appareil photo verticalement en raison de la façon dont il est assemblé. Si ce n'est pas votre cas, commentez ou supprimez la ligne de commande « flip ».

Vous pouvez également télécharger le code depuis mon GitHub : simpleCamTest.py

Pour exécuter, entrez la commande :

python simpleCamTest.py

Pour terminer le programme, vous devez appuyer sur la touche [q] ou [Ctrl] + [C] de votre clavier

La photo montre le résultat.

Pour en savoir plus sur OpenCV, vous pouvez suivre le tutoriel : loading -video-python-opencv-tutorial

Étape 4 :Détection des couleurs en Python avec OpenCV

Une chose que nous essaierons d'accomplir sera la détection et le suivi d'un certain objet de couleur. Pour cela, nous devons mieux comprendre comment OpenCV interprète les couleurs.

Henri Dang a écrit un excellent tutoriel sur la détection des couleurs en Python avec OpenCV.

Habituellement, notre appareil photo fonctionnera avec le mode couleur RVB, qui peut être compris en le considérant comme toutes les couleurs possibles pouvant être constituées de trois lumières colorées pour le rouge, le vert et le bleu. Nous travaillerons ici avec BGR (Bleu, Vert, Rouge) à la place.

Comme décrit ci-dessus, avec BGR, un pixel est représenté par 3 paramètres, bleu, vert et rouge. Chaque paramètre a généralement une valeur de 0 à 255 (ou de O à FF en hexadécimal). Par exemple, un pixel bleu pur sur votre écran d'ordinateur aurait une valeur B de 255, une valeur G de 0 et une valeur R de 0.

OpenCV fonctionne avec le modèle de couleur HSV (Hue, Saturation, Value), c'est-à-dire une représentation alternative du modèle de couleur RVB, conçu dans les années 1970 par des chercheurs en infographie pour s'aligner plus étroitement sur la façon dont l'homme la vision perçoit les attributs chromogènes :

Super. Ainsi, si vous souhaitez suivre une certaine couleur à l'aide d'OpenCV, vous devez la définir à l'aide du modèle HSV.

Exemple

Disons que je dois suivre un objet jaune car la boîte en plastique montrée sur l'image ci-dessus. La partie facilité est de trouver ses éléments BGR. Vous pouvez utiliser n'importe quel programme de conception pour le trouver (j'ai utilisé PowerPoint).

Dans mon cas, j'ai trouvé :

  • Bleu :71
  • Vert :234
  • Rouge :213

Ensuite, nous devons convertir le modèle BGR (71, 234, 213) en un modèle HSV, qui sera défini avec des limites supérieures et inférieures. Pour cela, exécutons le code ci-dessous :

importer sysimport numpy en tant que npimport cv2blue =sys.argv[1]green =sys.argv[2]red =sys.argv[3] color =np.uint8([[[bleu, vert , rouge]]])hsv_color =cv2.cvtColor(color, cv2.COLOR_BGR2HSV)hue =hsv_color[0][0][0]print("La limite inférieure est :"),print("[" + str(hue- 10) + ", 100, 100]\n")print("La limite supérieure est :"),print("[" + str(hue + 10) + ", 255, 255]")

Vous pouvez également télécharger le code depuis mon GitHub : bgr_hsv_converter.py

Pour exécuter, entrez la commande ci-dessous ayant comme paramètres les valeurs BGR trouvées auparavant :

python bgr_hsv_converter.py 71 234 213

Le programme imprimera les limites supérieure et inférieure de la couleur de notre objet.

Dans ce cas :

borne inférieure :[24, 100, 100]

et

borne supérieure :[44, 255, 255]

Le Terminal PrintScreen affiche le résultat.

Enfin, mais non des moindres, voyons comment OpenCV peut « masquer » notre objet une fois que nous avons déterminé sa couleur :

import cv2import numpy as np# Lire l'image - Le 1 signifie que nous voulons l'image dans BGRimg =cv2.imread('yellow_object.JPG', 1) # redimensionner l'image à 20% dans chaque axisimg =cv2.resize(img, (0,0), fx=0.2, fy=0.2)# convertir l'image BGR en une image HSVhsv =cv2.cvtColor(img, cv2.COLOR_BGR2HSV) # NumPy pour créer des tableaux pour contenir le bas et le haut range # Le "dtype =np.uint8" signifie que le type de données est un entier de 8 bitslower_range =np.array([24, 100, 100], dtype=np.uint8) upper_range =np.array([44, 255, 255 ], dtype=np.uint8)# crée un masque pour imagemask =cv2.inRange(hsv, lower_range, upper_range)# affiche à la fois le masque et l'image côte à côtecv2.imshow('mask',mask)cv2.imshow ('image', img)# attendre que l'utilisateur appuie sur [ ESC ]while(1) :k =cv2.waitKey(0) if(k ==27):breakcv2.destroyAllWindows()

Vous pouvez également télécharger le code depuis mon GitHub : colorDetection.py

Pour exécuter, saisissez la commande ci-dessous en ayant dans votre répertoire une photo avec votre objet cible (dans mon cas :yellow_object.JPG) :

python colorDetection.py

L'image ci-dessus montrera l'image d'origine ("image") et comment l'objet apparaîtra ("masque") après l'application du masque.

Étape 5 :Suivi des mouvements d'objets

Maintenant que nous savons "sélectionner" notre objet à l'aide d'un masque, suivons son mouvement en temps réel à l'aide de la caméra. Pour cela, j'ai basé mon code sur le didacticiel Ball Tracking with OpenCV d'Adrian Rosebrock.

Je vous suggère fortement de lire le tutoriel d'Adrian en détail.

Tout d'abord, vérifiez si vous disposez de la bibliothèque imutils installée. il s'agit de la collection de fonctions pratiques OpenCV d'Adrian pour faciliter certaines tâches de base (comme le redimensionnement ou le retournement de l'écran). Sinon, entrez avec la commande ci-dessous pour installer la bibliothèque sur votre environnement Virtual Python :

pip install imutils

Ensuite, téléchargez le code ball_tracking.py depuis mon GitHub et exécutez-le à l'aide de la commande :

python ball_traking.py

En gros, c'est le même code que celui d'Adrian sauf le "vidéo vertical flip", que j'ai obtenu avec la ligne :

frame =imutils.rotate(frame, angle=180)

En outre, notez que les limites de masque utilisées sont celles que nous avons obtenues à l'étape précédente.

Étape 6 :Tester les GPIO

Maintenant que nous avons joué avec les bases d'OpenCV, installons une LED sur notre RPi et commençons à interagir avec nos GPIO.

Suivez le schéma électrique ci-dessus :la cathode de la LED sera connectée au GPIO 21 et son anode au GND via une résistance de 220 ohms.

Testons notre LED dans notre environnement Python virtuel.

N'oubliez pas qu'il est possible que RPi.GPIO ne soit pas installé dans votre environnement virtuel Python ! Pour résoudre ce problème, une fois sur place (n'oubliez pas de confirmer que le (cv) est dans votre terminal), vous devez utiliser pip pour l'installer dans votre environnement virtuel :

pip installer RPi.GPIO

Utilisons le script python pour exécuter un test simple :

importer sysimport timeimport RPi.GPIO en tant que GPIO# initialiser GPIO et variablesredLed =int(sys.argv[1])freq =int(sys.argv[2])GPIO.setmode(GPIO.BCM )GPIO.setup(redLed, GPIO.OUT)GPIO.setwarnings(False)print("\n [INFO] LED clignotante (5 fois) connectée au GPIO {0} toutes les {1} seconde(s)".format( redLed, freq))for i in range(5) :GPIO.output(redLed, GPIO.LOW) time.sleep(freq) GPIO.output(redLed, GPIO.HIGH) time.sleep(freq)# faire un peu de cleanupprint("\n [INFO] Quitter le programme et nettoyer les choses \n")GPIO.cleanup()

Ce code recevra comme arguments un numéro GPIO et la fréquence en secondes à laquelle notre LED doit clignoter. La LED clignotera 5 fois et le programme sera terminé. Notez qu'avant de terminer, nous libérerons les GPIO.

Donc, pour exécuter le script, vous devez entrer comme paramètres, LED GPIO , et fréquence .

Par exemple :

python LED_simple_test.py 21 1

La commande ci-dessus fera clignoter 5 fois la LED rouge connectée à "GPIO 21" toutes les "1" seconde.

Le fichier GPIO_LED_test.py peut être téléchargé depuis mon GitHub

L'écran d'impression du terminal ci-dessus montre le résultat (et bien sûr, vous devez confirmer que la LED clignote.

Maintenant, travaillons avec OpenCV et quelques trucs GPIO de base.

Étape 7 :Reconnaître les couleurs et l'interaction GPIO

Commençons à intégrer nos codes OpenCV avec l'interaction GPIO. Nous commencerons par le dernier code OpenCV et nous y intégrerons la bibliothèque GPIO-RPI, nous allumerons donc la LED rouge à chaque fois que notre objet coloré sera trouvé par la caméra. Le code utilisé dans cette étape était basé sur l'excellent tutoriel d'Adrian OpenCV, RPi.GPIO et GPIO Zero sur le Raspberry Pi :

La première chose à faire est de « créer » notre LED, en la connectant au GPIO spécifique :

importer RPi.GPIO en tant que GPIOredLed =21GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)GPIO.setup(redLed, GPIO.OUT)

Deuxièmement, nous devons initialiser notre LED (éteinte) :

GPIO.output(redLed, GPIO.LOW)ledOn =False

Maintenant, à l'intérieur de la boucle, où le « cercle » est créé lorsque l'objet est trouvé, nous allons allumer la LED :

GPIO.output(redLed, GPIO.HIGH)ledOn =True

Téléchargeons le code complet depuis mon GitHub : object_detection_LED.py

Exécutez le code à l'aide de la commande :

python object_detection_LED.py

Essayez-le avec différents objets (couleur et format). Vous verrez qu'une fois que la couleur correspond à l'intérieur des limites du masque, la LED s'allume.

La vidéo ci-dessous montre quelques expériences. Notez que seuls les objets jaunes qui restent dans la gamme de couleurs seront détectés, ce qui allumera la LED. Les objets de couleurs différentes sont ignorés.

Nous n'utilisons ici que la LED comme expliqué dans la dernière étape. J'avais déjà assemblé mon Pan Tilt lorsque j'ai fait la vidéo, alors ignorez-le. Nous traiterons avec le mécanisme PAN/TILT à l'étape suivante.

Étape 8 : le mécanisme d'inclinaison panoramique

Maintenant que nous avons joué avec les bases d'OpenCV et GPIO, installons notre mécanisme Pan/tilt.

Pour plus de détails, veuillez visiter mon tutoriel : Pan-Tilt-Multi-Servo-Control

Les servos doivent être connectés à une alimentation externe 5V, leur broche de données (dans mon cas, leur câblage jaune) étant connectée au Raspberry Pi GPIO comme ci-dessous :

  • GPIO 17 ==> Servo d'inclinaison
  • GPIO 27 ==> Servo panoramique

N'oubliez pas de connecter les GND ensemble ==> Raspberry Pi – Servos – Alimentation externe)

Vous pouvez avoir en option, une résistance de 1K ohm en série, entre Raspberry Pi GPIO et broche d'entrée de données du serveur. Cela protégerait votre RPi en cas de problème de servo.

Profitons également de l'opportunité et testons nos servos dans notre environnement Python virtuel.

Utilisons le script Python pour exécuter quelques tests avec nos pilotes :

à partir du moment importer sleepimport RPi.GPIO en tant que GPIOGPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)def setServoAngle(servo, angle):pwm =GPIO.PWM(servo, 50) pwm .start(8) dutyCycle =angle / 18. + 3. pwm.ChangeDutyCycle(dutyCycle) sleep(0.3) pwm.stop()if __name__ =='__main__':import sys servo =int(sys.argv[1]) GPIO.setup(servo, GPIO.OUT) setServoAngle(servo, int(sys.argv[2])) GPIO.cleanup()

Le noyau du code ci-dessus est la fonction setServoAngle(servo, angle). Cette fonction reçoit comme arguments, un numéro GPIO d'asservissement et une valeur d'angle par rapport à l'endroit où le servo doit être positionné. Une fois que l'entrée de cette fonction est « angle », nous devons la convertir en un rapport cyclique équivalent.

Pour exécuter le script, vous devez saisir comme paramètres, servo GPIO , et angle .

Par exemple :

angle pythonServoCtrl.py 17 45

La commande ci-dessus positionnera le servo connecté sur GPIO 17 ("inclinaison") avec 45 degrés en "élévation".

Le fichier angleServoCtrl.py peut être téléchargé depuis mon GitHub

Étape 9 :Trouver la position en temps réel de l'objet

L'idée ici sera de positionner l'objet au milieu de l'écran à l'aide du mécanisme Pan/Tilt. La mauvaise nouvelle est que pour démarrer il faut savoir où se trouve l'objet en temps réel. Mais la bonne nouvelle est que c'est très facile, une fois que nous avons déjà les coordonnées du centre de l'objet.

Prenons d'abord le code "object_detect_LED" utilisé précédemment et modifions-le pour imprimer les coordonnées x,y de l'objet fondé.

Télécharger depuis mon GitHub le code : objectDetectCoord.py

Le « noyau » du code est la partie où nous trouvons l'objet et dessinons un cercle dessus avec un point rouge en son centre.

# ne procéder que si le rayon atteint une taille minimale si rayon> 10 :# tracer le cercle et le centroïde sur le cadre, # puis mettre à jour la liste des points suivis cv2.circle(frame, (int( x), int(y)), int(radius), (0, 255, 255), 2) cv2.circle(frame, center, 5, (0, 0, 255), -1) # imprimer le centre du cercle coordonnées mapObjectPosition(int(x), int(y)) # si la led n'est pas déjà allumée, allumer la led sinon ledOn :GPIO.output(redLed, GPIO.HIGH) ledOn =True

Exportons les coordonnées du centre vers mapObjectPosition(int(x), int(y)) fonction afin d'imprimer ses coordonnées. Sous la fonction :

def mapObjectPosition (x, y) :print ("[INFO] Object Center se coordonne à X0 ={0} et Y0 ={1}".format(x, y))

En exécutant le programme, nous verrons sur notre terminal les coordonnées de position (x, y), comme indiqué ci-dessus. Déplacez l'objet et observez les coordonnées. On se rendra compte que x va de 0 à 500 (de gauche à droite) et y va de o à 350 (de haut en bas). Voir les images ci-dessus.

Super ! Nous devons maintenant utiliser ces coordonnées comme point de départ pour notre système de suivi Pan/Tilt

Étape 10 : Système de suivi de la position des objets

Nous voulons que notre objet reste toujours centré sur l'écran. Alors, définissons par exemple, que l'on considérera notre objet « centré » si :

  • 220
  • 160

En dehors de ces limites, nous devons déplacer notre mécanisme Pan/Tilt pour compenser la déviation. Sur cette base, nous pouvons créer la fonction mapServoPosition(x, y) comme ci-dessous. Notez que les « x » et « y » utilisés comme paramètres dans cette fonction sont les mêmes que ceux que nous avons utilisés auparavant pour l'impression de la position centrale :

# positionner les servos pour présenter l'objet au centre du framedef mapServoPosition (x, y):global panAngle global tiltAngle if (x <220):panAngle +=10 if panAngle> 140:panAngle =140 positionServo (panServo, panAngle) if (x> 280) :panAngle -=10 si panAngle <40 :panAngle =40 positionServo (panServo, panAngle) if (y <160) :tiltAngle +=10 si tiltAngle> 140 :tiltAngle =140 positionServo (tiltServo, tiltAngle) si (y> 210):tiltAngle -=10 si tiltAngle <40:tiltAngle =40 positionServo (tiltServo, tiltAngle)

En fonction des coordonnées (x, y), des commandes de position d'asservissement sont générées à l'aide de la fonction positionServo(servo, angle). Par exemple, supposons que la position y soit « 50 », ce qui signifie que notre objet est presque en haut de l'écran, cela peut se traduire par le fait que « vue de la caméra » est « faible » (disons un angle d'inclinaison de 120 degrés) Nous devons donc « diminuer » l'angle d'inclinaison (disons à 100 degrés), de sorte que le viseur de la caméra sera « haut » et l'objet « descendra » à l'écran (y augmentera jusqu'à, disons, 190).

Le diagramme ci-dessus montre l'exemple en termes de géométrie.

Pensez au fonctionnement de la caméra panoramique. notez que l'écran n'est pas en miroir, ce qui signifie que si vous déplacez l'objet vers "votre gauche", il se déplacera à l'écran pour "votre droite", une fois que vous serez en opposition avec la caméra.

La fonction positionServo(servo, angle) peut être écrite comme :

def positionServo (servo, angle) :os.system("python angleServoCtrl.py " + str(servo) + " " + str(angle)) print("[INFO] Positionnement du servo à GPIO {0} à {1} degrés\n".format(servo, angle))

Nous appellerons le script indiqué précédemment pour le positionnement des servos.

Notez que angleServoCtrl.py doit être dans le même répertoire que objectDetectTrac.py

Le code complet peut être téléchargé depuis mon GitHub : objectDetectTrack.py

Étape 11 : Conclusion

Comme toujours, j'espère que ce projet pourra aider d'autres personnes à trouver leur chemin dans le monde passionnant de l'électronique !

Pour plus de détails et le code final, veuillez visiter mon dépôt GitHub : OpenCV-Object-Face-Tracking

Pour plus de projets, veuillez visiter mon blog : MJRoBot.org

Saludos du sud du monde !

À bientôt dans mon prochain tutoriel !

Merci,

Source :  Suivi automatique des objets de vision


Processus de fabrication

  1. Programmation orientée objet Python
  2. Suivi de la boule Raspberry Pi
  3. Speathe
  4. Reconnaissance faciale en temps réel :un projet de bout en bout
  5. Python - Orienté Objet
  6. Détermination de la précision du suivi dynamique des objets
  7. Le filtre améliore la vision du robot sur l'estimation de pose 6D
  8. Qu'est-ce qu'une presse automatique ?
  9. Qu'est-ce qu'une presse automatique ?