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

voiture robot intelligente de suivi du visage

Composants et fournitures

Créateur Ci20
× 1
Drivers de moteur SparkFun Dual H-Bridge L298
× 1
Batterie Li-Ion 1000mAh
× 1
Servos (Tower Pro MG996R)
× 2
Caméra (générique)
× 1
Kit de base pour robot GoPiGo Dexter Industries
× 1
Arduino Nano R3
× 1
Capteur à ultrasons - HC-SR04 (Générique)
× 1

Applications et services en ligne

Arduino IDE
OpenCV

À propos de ce projet

C'est une voiture qui traque ton visage, si je suis absent il vient !

Vous devez avoir installé ceci (Ci20) :

  • Opencv
  • Python
  • Autorisations de correction de port série

J'ai utilisé la distribution Debian 8 installer et télécharger

J'ai utilisé :

  • Ancien appareil photo pour ordinateur portable (recyclé)
  • Module de télémétrie à ultrasons HC - SR04
  • x2 Batterie 3.7v 4000mah (ancien ordinateur portable recyclé)
  • Servo x2
  • Convertisseur DC-DC
  • Arduino nano
  • Kit de base de robot
  • x2 L298d

Pour l'installation, utilisez les commandes suivantes dans le terminal.

Pour mettre à jour Linux.

sudo apt-get update # Récupère la liste des mises à jour disponiblessudo apt-get upgrade # Met à jour strictement les packages actuelssudo apt-get dist-upgrade # Installe les mises à jour (nouvelles) 

OpenCV. C'est la version 2.4.9.1 qui n'est pas à jour, mais ça marche bien.

sudo apt-get install libopencv-dev python-opencv 

Si vous voulez compiler OpenCV à partir de la source, j'ai trouvé ce tutoriel.

Installez PySerial.

sudo apt-get install python python-serial 

Nous modifions les autorisations du port série, si vous avez utilisé l'USB ou un natif.

sudo chown ci20:ci20 /dev/ttyUSB0 #Serial port USB from Arduinosudo chown ci20:ci20 /dev/ttyS1 #Serial port native in Ci20 

Exécute le script python (change le zéro si vous avez plus d'une source vidéo, cela sélectionne la source).

sudo python facetrackingcar.py 0 

Pour améliorer légèrement les performances, l'image capturée ne s'affiche pas si vous voulez voir, vous devez rechercher et décommenter ces lignes.

#cv.ShowImage("result", img)#cv.NamedWindow("result", 1)#cv.DestroyWindow("result") 

Vous devez avoir le haarcascade_frontalface_alt.xml fichier dans le même répertoire que le script.

Vidéo pour caméra de suivi uniquement sous Windows

Vidéo de démonstration sur Ci20

Les commentaires et les améliorations sont les bienvenus.

Code

  • faceser.py
  • Car.ino
  • scanlinux.py
faceser.pyPython
Python script OpenCV face traking
#!/usr/bin/python"""Ce programme est une démonstration pour la détection de visages et d'objets à l'aide de fonctionnalités de type haar. Le programme trouve les visages dans une image de caméra ou un flux vidéo et affiche une boîte rouge autour d'eux, puis centre la webcam via deux servos afin que le visage soit au centre de l'écranBasé sur faceetect.py dans le répertoire d'exemples OpenCV"""import sysfrom optparse import OptionParserimport serialimport cv2.cv as cvimport time# Paramètres pour la détection haar# Depuis l'API :# Les paramètres par défaut (scale_factor=2, min_neighbors=3, flags=0) sont réglés# pour une détection d'objet précise mais lente. Pour une opération plus rapide sur de vraies images vidéo#, les paramètres sont :# scale_factor=1.2, min_neighbors=2, flags=CV_HAAR_DO_CANNY_PRUNING,# min_size=>> servo.move(2, 90) ... # "move servo #2 à 90 degrés"''' if (min_pwm <=angle <=max_pwm):ser.write(chr(255)) ser.write(chr(servo)) ser.write(chr(angle)) else:print "Servo l'angle doit être un entier compris entre 0 et 180.\n"if __name__ =='__main__' :ser=serial.Serial(port='/dev/ttyUSB0',baudrate=115200,timeout=1) #ser=serial.Serial (port='/dev/ttyS0',baudrate=115200,timeout=1) #ser=serial.Serial(port='COM14',baudrate=115200,timeout=1) # analyser les options de ligne cmd, configurer Haar classifier parser =OptionParser(usage ="usage :%prog [options] [index_caméra]") parser.add_option("-c", "--cascade", action="store", dest="cascade", type="str", help="Fichier cascade Haar, par défaut %default", default ="./haarcascade_frontalface_alt.xml") (options, args) =parser.parse_args() cascade =cv.Load(options.cascade) if len(args) !=1:parser.print_help() sys.exit(1) input_name =arg s[0] if input_name.isdigit() :capture =cv.CreateCameraCapture(int(input_name)) cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH, 320) cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT, 320) cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT, Nous avons besoin d'une entrée caméra ! Spécifiez l'index de la caméra, par ex. 0" sys.exit(0) # cv.NamedWindow("result", 1) si capture :frame_copy =None move(panGpioPin, servoPanPosition) move(tiltGpioPin, servoTiltPosition) tandis que True :start =time.time() frame =cv .QueryFrame(capture) sinon frame :cv.WaitKey(0) break sinon frame_copy :frame_copy =cv.CreateImage((frame.width,frame.height), cv.IPL_DEPTH_8U, frame.nChannels) si frame.origin ==cv.IPL_ORIGIN_TL :cv.Copy(frame, frame_copy) else :cv.Flip(frame, frame_copy, 0) midScreenX =(frame.width/2) midScreenY =(frame.height/2) midFace =detect_and_draw(frame_copy, cascade) si midFace n'est pas None :midFaceX =midFace[0] midFaceY =midFace[1] #Découvrez si la composante X du visage est à gauche du milieu de l'écran. if(midFaceX <(midScreenX - midScreenWindow)):#Mettre à jour la variable de position panoramique pour déplacer le servo vers la droite.servoPanPosition +=panStepSize print str(midFaceX) + "> " + str(midScreenX) + " :Pan Right :" + str(servoPanPosition) #Découvrez si le X composant du visage est à la r droite du milieu de l'écran. elif(midFaceX> (midScreenX + midScreenWindow)):#Mettre à jour la variable de position panoramique pour déplacer le servo vers la gauche. servoPanPosition -=panStepSize print str(midFaceX) + " <" + str(midScreenX) + " :Pan Left :" + str(servoPanPosition) else:print str(midFaceX) + " ~ " + str(midScreenX) + " :" + str(servoPanPosition) servoPanPosition =min(servoPanPosition, max_pwm) servoPanPosition =max(servoPanPosition, min_pwm) move(panGpioPin, servoPanPosition) #Découvrez si la composante Y du visage est en dessous du milieu de l'écran. if(midFaceY <(midScreenY - midScreenWindow)):if(servoTiltPosition <=90):#Mettre à jour la variable de position d'inclinaison pour abaisser le servo d'inclinaison. servoTiltPosition -=tiltStepSize print str(midFaceY) + "> " + str(midScreenY) + " :Tilt Down :" + str(servoTiltPosition) #Découvrez si la composante Y du visage est au-dessus du milieu de l'écran. elif(midFaceY> (midScreenY + midScreenWindow)):if(servoTiltPosition>=1) :#Mettre à jour la variable de position d'inclinaison pour augmenter le servo d'inclinaison. servoTiltPosition +=tiltStepSize print str(midFaceY) + " <" + str(midScreenY) + " :Tilt Up :" + str(servoTiltPosition) start =1; fin =1 ; else :print str(midFaceY) + " ~ " + str(midScreenY) + " :" + str(servoTiltPosition) servoTiltPosition =min(servoTiltPosition, max_pwm) servoTiltPosition =max(servoTiltPosition, min_pwm) move(tiltGpio) end mesurer le temps end =time.time()+0.1 var +=0.1 # obtenir le temps écoulé time_elapsed =int(end - start + var) # imprimer les informations print 'time elapsed:\t{}'.format(time_elapsed) print ' var:\t{}'.format(var) if time_elapsed ==20:move(3, servoTiltPosition) servoPanPosition =90 servoTiltPosition =45 var=0; if cv.WaitKey(1)>=0 :# 1 ms de pause #cv.DestroyWindow("result")
Car.inoArduino
#include #define MA_1 2#define MA_2 3#define MB_1 4#define MB_2 5#define MC_1 6#define MC_2 7#define MD_1 8#define MD_2 9#define SERVOX_PIN 11#define SERVOY_PIN 10 #define trigPin 13#define echoPin 12// Entrée utilisateur pour servo et positionServo servoy;Servo servox;int x =90, prevX;int y =45, prevY;int userInput[3]; // entrée brute du tampon série, 3 bytesint startbyte ; // start byte, commence à lire inputint servo; // quel servo pulser?int pos; // angle d'asservissement 0-180int i; // iteratorint State =LOW;unsigned long previousMillis =0 , val =100;;const long interval =100;bool scana =false;unsigned long currentMillis;void setup() { inicializate(); currentMillis =millis();}void loop() { // Attend l'entrée série (min 3 octets dans le tampon) if (Serial.available()> 2) { // Lit le premier octet startbyte =Serial.read(); // Si c'est vraiment le startbyte (255) ... if (startbyte ==255) { // ... alors récupère les deux prochains octets pour (i =0; i <2; i++) { userInput[i] =Serial.read(); } // Premier octet =servo à déplacer ? servo =userInput[0] ; // Deuxième octet =quelle position ? pos =userInput[1] ; // Vérification et récupération des erreurs de paquet if (pos ==255) { servo =255; } // Attribuer une nouvelle position au commutateur d'asservissement approprié (servo) { case 1 :servoy.write(pos); // déplace le servo1 vers la pause 'pos' ; cas 2:servox.write(pos); gamme(pos); Pause; cas 3 :scan (45); scanner (65) ; Pause; par défaut :pause ; } } }}void scan(int val) { while (Serial.available() ==0) { servoy.write(val); non signé long currentMillis =millis(); if (currentMillis - previousMillis>=intervalle) { previousMillis =currentMillis; servox.write(pos); if (État ==BAS ) { pos +=1; if (pos ==130) { État =HAUT; } } else { pos -=1; if (pos ==40) { État =BAS; Pause; } } } }}longue distance() { longue durée, distance; digitalWrite(trigPin, LOW); // Ajout de cette ligne delayMicroseconds(2); // Ajout de cette ligne digitalWrite(trigPin, HIGH); délaiMicrosecondes(10) ; // Ajout de cette ligne digitalWrite(trigPin, LOW); durée =pulseIn(echoPin, HIGH); distance =(durée / 2) / 29,1 ; return distance;}void range(int pos) { if ((pos>=80 ) &(pos <=100)) { move(); } else if ((pos>=100 ) &(pos <=180)) { left(); retard(10) ; Arrêter(); } else if ((pos>=1 ) &(pos <=80)) { right(); retard(10) ; Arrêter(); }}mouvements vides() { longue distance, previusdistance; distance =distance(); if (val <=80) { reverse(); retard (50); Arrêter(); } else if (val>=140) { forward(); retard (50); Arrêter(); } if (distance>=previusdistance) { val =(distance - previusdistance); } else if (distance <=previusdistance) { val =(previusdistance - distance); } previusdistance =distance;}void inicializate() { Serial.begin(115200); pinMode(MA_1, SORTIE); pinMode(MA_2, SORTIE); pinMode(MB_1, SORTIE); pinMode(MB_2, SORTIE); pinMode(MC_1, SORTIE); pinMode(MC_2, SORTIE); pinMode(MD_1, SORTIE); pinMode(MD_2, SORTIE); pinMode(trigPin, SORTIE); pinMode(echoPin, INPUT); servox.attach(SERVOX_PIN); servoy.attach(SERVOY_PIN);}void forward() { digitalWrite(MA_1, HIGH); digitalWrite(MA_2, LOW); digitalWrite(MB_1, HAUT); digitalWrite(MB_2, LOW); digitalWrite(MC_1, HAUT); digitalWrite(MC_2, LOW); digitalWrite(MD_1, HAUT); digitalWrite(MD_2, LOW);}void reverse () { digitalWrite(MA_1, LOW); digitalWrite(MA_2, HAUT); digitalWrite(MB_1, LOW); digitalWrite(MB_2, HAUT); digitalWrite(MC_1, LOW); digitalWrite(MC_2, HAUT); digitalWrite(MD_1, LOW); digitalWrite(MD_2, HIGH);}void right() { digitalWrite(MA_1, LOW); digitalWrite(MA_2, HAUT); digitalWrite(MB_1, LOW); digitalWrite(MB_2, HAUT); digitalWrite(MC_1, HAUT); digitalWrite(MC_2, LOW); digitalWrite(MD_1, HAUT); digitalWrite(MD_2, LOW);}void left() { digitalWrite(MA_1, HIGH); digitalWrite(MA_2, LOW); digitalWrite(MB_1, HAUT); digitalWrite(MB_2, LOW); digitalWrite(MC_1, LOW); digitalWrite(MC_2, HAUT); digitalWrite(MD_1, LOW); digitalWrite(MD_2, HIGH);}void Stop() { digitalWrite(MA_1, LOW); digitalWrite(MA_2, LOW); digitalWrite(MB_1, LOW); digitalWrite(MB_2, LOW); digitalWrite(MC_1, LOW); digitalWrite(MC_2, LOW); digitalWrite(MD_1, LOW); digitalWrite(MD_2, LOW);}void StopH() { digitalWrite(MA_1, HIGH); digitalWrite(MA_2, HAUT); digitalWrite(MB_1, HAUT); digitalWrite(MB_2, HAUT); digitalWrite(MC_1, HAUT); digitalWrite(MC_2, HAUT); digitalWrite(MD_1, HAUT); digitalWrite(MD_2, HIGH);}
scanlinux.pyPython
Scannez les ports série Linux
# ! /usr/bin/env python"""\Scan pour les ports série. Variante spécifique à Linux qui inclut également les adaptateurs USB/Serial.Part of pySerial (http://pyserial.sf.net)(C) 2009 """import serialimport globdef scan():""" recherche les ports disponibles. renvoie une liste des noms de périphériques. pvergain@houx:~/PDEV1V160_CodesRousseau/Soft/PC/test_boost/serialport/pyserial$ python scanlinux.py Ports trouvés :/dev/ttyS0 /dev/ttyS3 /dev/ttyS2 /dev/ttyS1 /dev/ttyACM0 /dev/serial/by-id/usb-id3_semiconductors_MEABOARD_00000000-if00 """ return glob.glob('/dev/ttyS*' ) + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') + glob.glob('/dev/serial/by-id/*')if __name__==' __main__' : imprimer "Ports trouvés : » pour le nom dans scan() :imprimer le nom

Pièces et boîtiers personnalisés

Python script OpenCV Face Traking et Arduino Code FaceTrakingCar.rar

Schémas

En utilisant l'arduino pour contrôler les moteurs et les servos, le brochage peut varier.

Processus de fabrication

  1. Dés numériques Arduino
  2. Jeu de roulette DIY 37 LED
  3. Mini arcade ATtiny85 :Serpent
  4. Détecteur de portée portable
  5. MobBob :Robot Arduino DIY contrôlé par smartphone Android
  6. Robot piano contrôlé par Arduino :PiBot
  7. La galvanoplastie avec du cuivre
  8. NeoMatrix Arduino Pong
  9. Robot convivial de suivi des personnes omnidirectionnel