Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Coche robot inteligente de seguimiento facial

Componentes y suministros

Creator Ci20
× 1
Controladores de motor SparkFun Dual H-Bridge L298
× 1
Batería de iones de litio de 1000 mAh
× 1
Servos (Tower Pro MG996R)
× 2
Cámara (genérica)
× 1
Kit básico de robot GoPiGo de Dexter Industries
× 1
Arduino Nano R3
× 1
Sensor ultrasónico - HC-SR04 (genérico)
× 1

Aplicaciones y servicios en línea

Arduino IDE
OpenCV

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.rar

Esquemas

Usando el arduino para controlar motores y servos, la asignación de pines puede variar.

Proceso de manufactura

  1. Dados digitales Arduino
  2. Juego de ruleta DIY 37 LED
  3. ATtiny85 Mini Arcade:Serpiente
  4. Detector de alcance portátil
  5. MobBob:Robot Arduino DIY controlado por un teléfono inteligente Android
  6. Robot de piano controlado por Arduino:PiBot
  7. Galvanoplastia con cobre
  8. NeoMatrix Arduino Pong
  9. Robot amigable de seguimiento de personas omnidireccional
  10. Creador de secuencias de luz
  11. Puerta inteligente con desbloqueo facial