Coche robot inteligente de seguimiento facial
Componentes y suministros
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Aplicaciones y servicios en línea
| ||||
|
Acerca de este proyecto
Es un auto que rastrea tu rostro, si yo me voy, viene!
Necesita tener instalado esto (Ci20):
- Opencv
- Python
- Permisos de corrección del puerto serie
Usé la distribución Debian 8 install & download
Yo usé:
- Cámara de portátil vieja (reciclada)
- Módulo de rango ultrasónico HC - SR04
- x2 Batería 3.7v 4000mah (laptop vieja reciclada)
- x2 Servo
- Convertidor CC-CC
- Arduino nano
- Kit básico de robot
- x2 L298d
Para la instalación, use los siguientes comandos en la terminal.
Para actualizar linux.
sudo apt-get update # Obtiene la lista de actualizaciones disponibles sudo apt-get upgrade # Actualiza estrictamente el paquete actual sudo apt-get dist-upgrade # Instala actualizaciones (nuevas)
OpenCV. Es que la versión 2.4.9.1 no está actualizada, pero funciona bien.
sudo apt-get install libopencv-dev python-opencv
Si desea compilar OpenCV desde la fuente, encontré este tutorial.
Instale PySerial.
sudo apt-get install python python-serial
Cambiamos los permisos del puerto serie, si usó el USB o un nativo.
sudo chown ci20:ci20 / dev / ttyUSB0 # Puerto serie USB de Arduinosudo chown ci20:ci20 / dev / ttyS1 # Puerto serie nativo en Ci20
Ejecuta el script de Python (cambia el cero si tiene más de una fuente de video, esto selecciona la fuente).
sudo python facetrackingcar.py 0
Para mejorar levemente el rendimiento, la imagen capturada no se muestra si desea verla, debe buscar y descomentar estas líneas.
# cv.ShowImage ("resultado", img) # cv.NamedWindow ("resultado", 1) # cv.DestroyWindow ("resultado")
Debes tener el haarcascade_frontalface_alt.xml archivo en el mismo directorio que el script.
Video solo para cámara de seguimiento en Windows
Video de demostración sobre Ci20
Los comentarios y las mejoras son bienvenidos.
Código
- faceser.py
- Car.ino
- scanlinux.py
faceser.py Python
Python scrip OpenCV face traking#! / Usr / bin / python "" "Este programa es una demostración para la detección de rostros y objetos utilizando funciones similares a las de haar. El programa encuentra rostros en una imagen de cámara o flujo de video y muestra un cuadro rojo alrededor de ellos, luego centra la cámara web a través de dos servos para que la cara esté en el centro de la pantalla Basado en facedetect.py en el directorio de muestras de OpenCV "" "import sysfrom optparse import OptionParserimport serialimport cv2.cv as cvimport time Desde la API:# Los parámetros predeterminados (scale_factor =2, min_neighbors =3, flags =0) están ajustados # para una detección de objetos precisa pero lenta. Para una operación más rápida en # imágenes de video reales, las configuraciones son:# scale_factor =1.2, min_neighbors =2, flags =CV_HAAR_DO_CANNY_PRUNING, # min_size =>> servo.move (2, 90) ... # "mover servo # 2 a 90 grados "'' 'if (min_pwm <=ángulo <=max_pwm):ser.write (chr (255)) ser.write (chr (servo)) ser.write (chr (ángulo)) else:print" Servo el ángulo debe ser un número entero entre 0 y 180. \ n "if __name__ =='__main__':ser =serial.Serial (port ='/ dev / ttyUSB0', baudrate =115200, timeout =1) # ser =serial.Serial (puerto ='/ dev / ttyS0', velocidad en baudios =115200, tiempo de espera =1) # ser =serial.Serial (puerto ='COM14', velocidad en baudios =115200, tiempo de espera =1) # analizar las opciones de la línea cmd, configurar el analizador del clasificador Haar =OptionParser (uso ="uso:% prog [opciones] [índice_cámara]") parser.add_option ("- c", "--cascade", action ="store", dest ="cascade", type ="str", help ="Archivo en cascada Haar, predeterminado% predeterminado", predeterminado ="./haarcascade_frontalface_alt.xml") (opciones, argumentos) =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_PRIMIR), si no, 240 ¡Necesitamos una entrada de cámara! Especifique el índice de la cámara, p. Ej. 0 "sys.exit (0) # cv.NamedWindow (" resultado ", 1) if capture:frame_copy =None move (panGpioPin, servoPanPosition) move (tiltGpioPin, servoTiltPosition) while True:start =time.time () frame =cv .QueryFrame (captura) si no es marco:cv.WaitKey (0) romper si no es 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, cascada) si midFace no es None:midFaceX =midFace [0] midFaceY =midFace [1] #Descubre si el componente X de la cara está a la izquierda del centro de la pantalla. if (midFaceX <(midScreenX - midScreenWindow)):#Actualiza la variable de posición panorámica para mover el servo a la derecha. ServoPanPosition + =panStepSize print str (midFaceX) + ">" + str (midScreenX) + ":Pan Right:" + str (servoPanPosition) #Descubre si la X componente de la cara es la r a la derecha del centro de la pantalla. elif (midFaceX> (midScreenX + midScreenWindow)):#Actualiza la variable de posición panorámica para mover el servo a la izquierda. 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) # Averigüe si el componente Y de la cara está debajo de la mitad de la pantalla. if (midFaceY <(midScreenY - midScreenWindow)):if (servoTiltPosition <=90):#Actualiza la variable de posición de inclinación para bajar el servo de inclinación. servoTiltPosition - =tiltStepSize print str (midFaceY) + ">" + str (midScreenY) + ":Tilt Down:" + str (servoTiltPosition) #Descubre si el componente Y de la cara está por encima del centro de la pantalla. elif (midFaceY> (midScreenY + midScreenWindow)):if (servoTiltPosition> =1):#Actualiza la variable de posición de inclinación para subir el servo de inclinación. servoTiltPosition + =tiltStepSize print str (midFaceY) + "<" + str (midScreenY) + ":Inclinar hacia arriba:" + str (servoTiltPosition) start =1; fin =1; de lo contrario:print str (midFaceY) + "~" + str (midScreenY) + ":" + str (servoTiltPosition) servoTiltPosition =min (servoTiltPosition, max_pwm) servoTiltPosition =max (servoTiltPosition, min_pwm) move (tiltGpiltioPin, servoTiltPosition) fin del tiempo de medición end =time.time () + 0.1 var + =0.1 # obteniendo el tiempo transcurrido time_elapsed =int (end - start + var) # imprimiendo información imprimir 'tiempo transcurrido:\ 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 delay break # cv.DestroyWindow ("resultado")
Car.ino Arduino
#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 // Entrada de usuario para servo y posiciónServo servoy; Servo servox; int x =90, prevX; int y =45, prevY; int userInput [3]; // entrada sin procesar del búfer en serie, 3 bytesint startbyte; // iniciar byte, comenzar a leer inputint servo; // ¿Qué servo pulsar? int pos; // ángulo del servo 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 () {// Espera la entrada en serie (mínimo 3 bytes en el búfer) if (Serial.available ()> 2) {// Lee el primer byte startbyte =Serial.read (); // Si es realmente el byte de inicio (255) ... if (startbyte ==255) {// ... entonces obtenga los siguientes dos bytes para (i =0; i <2; i ++) {userInput [i] =Serial.read (); } // ¿Primer byte =servo a mover? servo =userInput [0]; // Segundo byte =¿qué posición? pos =userInput [1]; // Comprobación y recuperación de errores de paquetes if (pos ==255) {servo =255; } // Asignar una nueva posición al interruptor de servo apropiado (servo) {caso 1:servoy.write (pos); // mover servo1 a 'pos' break; caso 2:servox.write (pos); rango (pos); descanso; caso 3:escanear (45); escanear (65); descanso; predeterminado:descanso; }}}} escaneo vacío (int val) {while (Serial.available () ==0) {servoy.write (val); currentMillis largo sin firmar =millis (); if (currentMillis - previousMillis> =intervalo) {previousMillis =currentMillis; servox.write (pos); si (Estado ==BAJO) {pos + =1; if (pos ==130) {Estado =ALTO; }} else {pos - =1; if (pos ==40) {Estado =BAJO; descanso; }}}}} long distancia () {larga duración, distancia; digitalWrite (trigPin, BAJO); // Añadida esta línea delayMicroseconds (2); // Añadida esta línea digitalWrite (trigPin, HIGH); delayMicroseconds (10); // Añadida esta línea digitalWrite (trigPin, LOW); duración =pulseIn (echoPin, HIGH); distancia =(duración / 2) / 29,1; distancia de retorno;} rango vacío (int pos) {if ((pos> =80) &(pos <=100)) {mueve (); } más si ((pos> =100) &(pos <=180)) {izquierda (); retraso (10); Detener(); } más si ((pos> =1) &(pos <=80)) {derecha (); retraso (10); Detener(); }} void mueve () {larga distancia, anterior distancia; distancia =distancia (); si (val <=80) {reverso (); retraso (50); Detener(); } más si (val> =140) {adelante (); retraso (50); Detener(); } if (distancia> =distancia anterior) {val =(distancia - distancia anterior); } else if (distancia <=distancia anterior) {val =(distancia anterior - distancia); } previusdistance =distancia;} void inicializate () {Serial.begin (115200); pinMode (MA_1, SALIDA); pinMode (MA_2, SALIDA); pinMode (MB_1, SALIDA); pinMode (MB_2, SALIDA); pinMode (MC_1, SALIDA); pinMode (MC_2, SALIDA); pinMode (MD_1, SALIDA); pinMode (MD_2, SALIDA); pinMode (trigPin, SALIDA); pinMode (echoPin, ENTRADA); servox.attach (SERVOX_PIN); servoy.attach (SERVOY_PIN);} void forward () {digitalWrite (MA_1, HIGH); digitalWrite (MA_2, BAJO); escritura digital (MB_1, ALTA); digitalWrite (MB_2, BAJO); escritura digital (MC_1, ALTA); digitalWrite (MC_2, BAJO); escritura digital (MD_1, ALTA); escritura digital (MD_2, BAJA);} anular inversa () {escritura digital (MA_1, BAJA); escritura digital (MA_2, ALTA); digitalWrite (MB_1, BAJO); escritura digital (MB_2, ALTA); escritura digital (MC_1, BAJA); escritura digital (MC_2, ALTA); digitalWrite (MD_1, BAJO); digitalWrite (MD_2, HIGH);} void right () {digitalWrite (MA_1, LOW); escritura digital (MA_2, ALTA); digitalWrite (MB_1, BAJO); escritura digital (MB_2, ALTA); escritura digital (MC_1, ALTA); digitalWrite (MC_2, BAJO); escritura digital (MD_1, ALTA); digitalWrite (MD_2, LOW);} vacío a la izquierda () {digitalWrite (MA_1, HIGH); digitalWrite (MA_2, BAJO); escritura digital (MB_1, ALTA); digitalWrite (MB_2, BAJO); escritura digital (MC_1, BAJA); escritura digital (MC_2, ALTA); digitalWrite (MD_1, BAJO); digitalWrite (MD_2, HIGH);} void Stop () {digitalWrite (MA_1, LOW); digitalWrite (MA_2, BAJO); digitalWrite (MB_1, BAJO); digitalWrite (MB_2, BAJO); escritura digital (MC_1, BAJA); digitalWrite (MC_2, BAJO); digitalWrite (MD_1, BAJO); escritura digital (MD_2, BAJA);} void StopH () {escritura digital (MA_1, ALTA); escritura digital (MA_2, ALTA); escritura digital (MB_1, ALTA); escritura digital (MB_2, ALTA); escritura digital (MC_1, ALTA); escritura digital (MC_2, ALTA); escritura digital (MD_1, ALTA); digitalWrite (MD_2, ALTA);}
scanlinux.py Python
¡Escanee los puertos seriales de Linux#! / usr / bin / env python "" "\ Buscar puertos serie. Variante específica de Linux que también incluye adaptadores USB / Seria. Parte de pySerial (http://pyserial.sf.net) (C) 2009"" "import serialimport globdef scan ():" "" escanea los puertos disponibles. Devuelve una lista de los nombres de los dispositivos. pvergain @ houx:~ / PDEV1V160_CodesRousseau / Soft / PC / test_boost / serialport / pyserial $ python scanlinux.py Puertos encontrados :/ 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__ ':imprime "Puertos encontrados:" para el nombre en el escaneo ():imprime el nombre
Piezas y carcasas personalizadas
Seguimiento facial de OpenCV de Python scrip y código Arduino FaceTrakingCar.rarEsquemas
Usando el arduino para controlar motores y servos, la asignación de pines puede variar.Proceso de manufactura
- Dados digitales Arduino
- Juego de ruleta DIY 37 LED
- ATtiny85 Mini Arcade:Serpiente
- Detector de alcance portátil
- MobBob:Robot Arduino DIY controlado por un teléfono inteligente Android
- Robot de piano controlado por Arduino:PiBot
- Galvanoplastia con cobre
- NeoMatrix Arduino Pong
- Robot amigable de seguimiento de personas omnidireccional
- Creador de secuencias de luz
- Puerta inteligente con desbloqueo facial