Industrielle Fertigung
Industrielles Internet der Dinge | Industrielle Materialien | Gerätewartung und Reparatur | Industrielle Programmierung |
home  MfgRobots >> Industrielle Fertigung >  >> Manufacturing Technology >> Herstellungsprozess

Smart Face Tracking Roboterauto

Komponenten und Verbrauchsmaterialien

Creator Ci20
× 1
SparkFun Dual H-Bridge Motortreiber L298
× 1
Li-Ionen-Akku 1000mAh
× 1
Servos (Tower Pro MG996R)
× 2
Kamera (allgemein)
× 1
Dexter Industries GoPiGo-Roboter-Basiskit
× 1
Arduino Nano R3
× 1
Ultraschallsensor - HC-SR04 (Generic)
× 1

Apps und Onlinedienste

Arduino-IDE
OpenCV

Über dieses Projekt

Es ist ein Auto, das dein Gesicht verfolgt, wenn ich weg bin, kommt er!

Sie müssen dies installiert haben (Ci20):

  • Opencv
  • Python
  • Berechtigungen zum Korrigieren von seriellen Ports

Ich habe die Distribution Debian 8 installiert und heruntergeladen

Ich habe verwendet:

  • Alte Laptopkamera (recycelt)
  • Ultraschall-Entfernungsmodul HC - SR04
  • x2 Batterie 3,7 V 4000 mAh (recycelter alter Laptop)
  • x2 Servo
  • DC-DC-Wandler
  • Arduino-Nano
  • Roboter-Basiskit
  • x2 L298d

Verwenden Sie zur Installation die folgenden Befehle im Terminal.

Um Linux zu aktualisieren.

sudo apt-get update # Ruft die Liste der verfügbaren Updates absudo apt-get upgrade # Aktualisiert strikt die aktuellen Paketesudo apt-get dist-upgrade # Installiert Updates (neue) 

OpenCV. Die Version 2.4.9.1 ist zwar nicht aktuell, funktioniert aber einwandfrei.

sudo apt-get install libopencv-dev python-opencv 

Wenn Sie OpenCV aus dem Quellcode kompilieren möchten, habe ich dieses Tutorial gefunden.

PySerial installieren.

sudo apt-get install python python-serial 

Wir ändern die Berechtigungen für den seriellen Port, wenn Sie den USB oder einen nativen verwendet haben.

sudo chown ci20:ci20 /dev/ttyUSB0 #Serielle Schnittstelle USB von Arduinosudo chown ci20:ci20 /dev/ttyS1 #Serielle Schnittstelle nativ in Ci20 

Führt das Python-Skript aus (ändert die Null, wenn Sie mehr als eine Videoquelle haben, dies wählt die Quelle aus).

sudo python facetrackingcar.py 0 

Um die Leistung etwas zu verbessern, wird das aufgenommene Bild nicht angezeigt, wenn Sie es sehen möchten. Sie müssen diese Zeilen suchen und auskommentieren.

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

Sie benötigen die haarcascade_frontalface_alt.xml Datei im selben Verzeichnis wie das Skript.

Video nur für die Verfolgungskamera in Windows

Demo-Video auf Ci20

Feedback und Verbesserungen sind willkommen.

Code

  • faceser.py
  • Car.ino
  • scanlinux.py
faceser.pyPython
Python-Skript OpenCV Face Traking
#!/usr/bin/python"""Dieses Programm ist eine Demonstration für die Gesichts- und Objekterkennung mit haarähnlichen Funktionen. Das Programm findet Gesichter in einem Kamerabild oder Videostream und zeigt ein rotes Kästchen an um sie herum, dann zentriert die Webcam über zwei Servos, so dass das Gesicht in der Mitte des Bildschirms istBasierend auf faceetect.py im OpenCV-Beispielverzeichnis"""import sysfrom optparse import OptionParserimport serialimport cv2.cv as cvimport time# Parameter for haar detection# Von der API:# Die Standardparameter (scale_factor=2, min_neighbors=3, flags=0) sind auf genaue, aber langsame Objekterkennung eingestellt#. Für einen schnelleren Betrieb auf echten Videobildern sind die Einstellungen:# scale_factor=1,2, min_neighbors=2, flags=CV_HAAR_DO_CANNY_PRUNING,# min_size=>> servo.move(2, 90) ... # "move servo #2 auf 90 Grad"''' if (min_pwm <=angle <=max_pwm):ser.write(chr(255)) ser.write(chr(servo)) ser.write(chr(angle)) else:print "Servo angle muss eine ganze Zahl zwischen 0 und 180 sein.\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) # Befehlszeilenoptionen analysieren, Haar-Klassifikator-Parser einrichten =OptionParser(usage ="usage:%prog [options] [camera_index]") parser.add_option("-c", "--cascade", action="store", dest="cascade", type="str", help="Haar cascade file, default %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 ", 240) Wir brauchen einen Kameraeingang! Kameraindex angeben, z.B. 0" sys.exit(0) # cv.NamedWindow("result", 1) if capture:frame_copy =None move(panGpioPin, servoPanPosition) move(tiltGpioPin, servoTiltPosition) while True:start =time.time() frame =cv .QueryFrame(capture) if not frame:cv.WaitKey(0) break falls nicht frame_copy:frame_copy =cv.CreateImage((frame.width,frame.height), cv.IPL_DEPTH_8U, frame.nChannels) if 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) if midFace ist nicht None:midFaceX =midFace[0] midFaceY =midFace[1] #Finde heraus, ob sich die X-Komponente des Gesichts links von der Mitte des Bildschirms befindet if(midFaceX <(midScreenX - midScreenWindow)):#Aktualisieren Sie die Pan-Positionsvariable, um das Servo nach rechts zu bewegen servoPanPosition +=panStepSize print str(midFaceX) + "> " + str(midScreenX) + " :Pan Right :" + str(servoPanPosition) #Finden Sie heraus, ob das X Bestandteil des Gesichts ist zum r in der Mitte des Bildschirms. elif(midFaceX> (midScreenX + midScreenWindow)):#Aktualisieren Sie die Schwenkpositionsvariable, um das Servo nach links zu bewegen. 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) #Finden Sie heraus, ob die Y-Komponente des Gesichts unter der Mitte des Bildschirms liegt. if(midFaceY <(midScreenY - midScreenWindow)):if(servoTiltPosition <=90):#Aktualisieren Sie die Neigungspositionsvariable, um das Neigungsservo abzusenken. servoTiltPosition -=TiltStepSize print str(midFaceY) + "> " + str(midScreenY) + " :Tilt Down :" + str(servoTiltPosition) #Finden Sie heraus, ob die Y-Komponente des Gesichts über der Mitte des Bildschirms liegt. elif(midFaceY> (midScreenY + midScreenWindow)):if(servoTiltPosition>=1):#Aktualisieren Sie die Neigungspositionsvariable, um das Neigungsservo anzuheben. servoTiltPosition +=TiltStepSize print str(midFaceY) + " <" + str(midScreenY) + " :Tilt Up :" + str(servoTiltPosition) start =1; Ende =1; else:print str(midFaceY) + " ~ " + str(midScreenY) + " :" + str(servoTiltPosition) servoTiltPosition =min(servoTiltPosition, max_pwm) servoTiltPosition =max(servoTiltPosition, min_pwm) move(tiltGpioPin, servoTiltPosition) else:# Ende der Messzeit end =time.time()+0.1 var +=0.1 # die verstrichene Zeit abrufen time_elapsed =int(end - start + var) # Informationen drucken 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:# 1ms Verzögerungspause #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// Benutzereingabe für Servo und PositionServo servoy;Servo servox;int x =90, prevX;int y =45, prevY;int userInput[3]; // Roheingabe vom seriellen Puffer, 3 Bytesint Startbyte; // Byte starten, mit dem Lesen beginnen Inputint Servo; // Welches Servo soll gepulst werden? Int pos; // Servowinkel 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() { // Warte auf serielle Eingabe (min 3 Bytes im Puffer) if (Serial.available()> 2) { // Lies das erste Byte startbyte =Serial.read(); // Wenn es wirklich das Startbyte (255) ist ... if (startbyte ==255) { // ... dann die nächsten zwei Bytes für (i =0; i <2; i++) { userInput[i] =Serial.read(); } // Erstes Byte =Servo zum Bewegen? servo =userInput[0]; // Zweites Byte =welche Position? pos =userInput[1]; // Paketfehlerprüfung und -wiederherstellung if (pos ==255) { Servo =255; } // Dem entsprechenden Servoschalter (Servo) eine neue Position zuweisen {Fall 1:servoy.write (pos); // Servo1 in 'pos' Pause bewegen; Fall 2:servox.write (pos); Reichweite(pos); brechen; Fall 3:Scannen (45); scannen (65); brechen; Vorgabe:Pause; } } }}void scan (int val) { Während (Serial.available () ==0) { servoy.write (val); unsigned long currentMillis =millis(); if (currentMillis - previousMillis>=Intervall) { previousMillis =currentMillis; servox.write (pos); if (Zustand ==NIEDRIG) {pos +=1; if (pos ==130) { State =HIGH; } } sonst { pos -=1; if (pos ==40) { State =LOW; brechen; } } }}} lange Distanz () { lange Dauer, Entfernung; digitalWrite (trigPin, LOW); // Diese Zeile hinzugefügt delayMicroseconds(2); // Diese Zeile hinzugefügt digitalWrite (trigPin, HIGH); VerzögerungMikrosekunden(10); // Diese Zeile hinzugefügt digitalWrite (trigPin, LOW); Dauer =pulseIn(echoPin, HIGH); Distanz =(Dauer / 2) / 29,1; Rückkehrabstand;} Leerer Bereich (int pos) { if ((pos>=80) &(pos <=100)) { bewegt (); aufrechtzuerhalten. Sonst if ((pos>=100) &(pos <=180)) { left(); Verzögerung(10); Halt(); aufrechtzuerhalten. Sonst if ((pos>=1 ) &(pos <=80)) { right(); Verzögerung(10); Halt(); }}void Moves () { Long Distance, Previusdistance; Distanz =Distanz (); if (val <=80) { reverse(); Verzögerung (50); Halt(); aufrechtzuerhalten. Sonst if (val>=140) { forward(); Verzögerung (50); Halt(); } if (Abstand>=Vorherabstand) { val =(Abstand - Vorabstand); aufrechtzuerhalten. Sonst if (Abstand <=Vorher-Abstand) { val =(Vorher-Abstand - Abstand); aufrechtzuerhalten. Vorheriger Abstand =Abstand;} Leere Initialisierung () { Serial.begin (115200); pinMode (MA_1, AUSGANG); pinMode (MA_2, AUSGANG); pinMode (MB_1, AUSGANG); pinMode (MB_2, AUSGANG); pinMode (MC_1, AUSGANG); pinMode (MC_2, AUSGANG); pinMode (MD_1, AUSGANG); pinMode (MD_2, AUSGANG); pinMode (trigPin, AUSGANG); pinMode (echoPin, EINGANG); servox.attach(SERVOX_PIN); servoy.attach (SERVOY_PIN);}void forward() { digitalWrite (MA_1, HIGH); digitalWrite (MA_2, LOW); digitalWrite(MB_1, HOCH); digitalWrite (MB_2, LOW); digitalWrite (MC_1, HOCH); digitalWrite (MC_2, LOW); digitalWrite(MD_1, HOCH); digitalWrite (MD_2, LOW);} ungültiger Rückwärtsgang () { digitalWrite (MA_1, LOW); digitalWrite (MA_2, HOCH); digitalWrite(MB_1, LOW); digitalWrite (MB_2, HOCH); digitalWrite (MC_1, LOW); digitalWrite (MC_2, HIGH); digitalWrite(MD_1, LOW); digitalWrite (MD_2, HIGH);} ungültiges Recht () { digitalWrite (MA_1, LOW); digitalWrite (MA_2, HOCH); digitalWrite(MB_1, LOW); digitalWrite (MB_2, HOCH); digitalWrite (MC_1, HOCH); digitalWrite (MC_2, LOW); digitalWrite(MD_1, HOCH); digitalWrite (MD_2, LOW);}void left() { digitalWrite (MA_1, HIGH); digitalWrite (MA_2, LOW); digitalWrite(MB_1, HOCH); digitalWrite (MB_2, LOW); digitalWrite (MC_1, LOW); digitalWrite (MC_2, HIGH); 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, HOCH); digitalWrite(MB_1, HOCH); digitalWrite (MB_2, HOCH); digitalWrite (MC_1, HOCH); digitalWrite (MC_2, HIGH); digitalWrite(MD_1, HOCH); digitalWrite(MD_2, HIGH);}
scanlinux.pyPython
Scannen Sie die seriellen Linux-Ports
#! /usr/bin/env python"""\Scan for serial ports. Linux-spezifische Variante, die auch USB/Serialadapters enthält.Part of pySerial (http://pyserial.sf.net)(C) 2009 """import serialimport globdef scan():"""Nach verfügbaren Ports scannen. Eine Liste der Gerätenamen zurückgeben. pvergain@houx:~/PDEV1V160_CodesRousseau/Soft/PC/test_boost/serialport/pyserial$ python scanlinux.py Gefundene Ports :/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__':"Gefundene Ports:" für Namen in scan() ausgeben:Name ausgeben

Kundenspezifische Teile und Gehäuse

Python-Skript OpenCV-Face-Traking und Arduino-Code FaceTrakingCar.rar

Schaltpläne

Bei Verwendung des Arduino zur Steuerung von Motoren und Servos kann die Pinbelegung variieren.

Herstellungsprozess

  1. Arduino Digital Dice
  2. DIY 37 LED-Roulette-Spiel
  3. ATtiny85 Mini Arcade:Schlange
  4. Tragbarer Reichweitendetektor
  5. MobBob:DIY-Arduino-Roboter, der von einem Android-Smartphone gesteuert wird
  6. Arduino-gesteuerter Klavierroboter:PiBot
  7. Galvanisieren mit Kupfer
  8. NeoMatrix Arduino Pong
  9. Omnidirektionale Personen, die freundlichen Roboter verfolgen
  10. Lichtsequenz-Ersteller