Carro robô rastreador Smart Face
Componentes e suprimentos
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
| × | 2 | ||||
| × | 1 | ||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 |
Aplicativos e serviços online
![]() |
| |||
![]() |
|
Sobre este projeto
É um carro que rastreia seu rosto, se eu for embora ele vem!
Você precisa ter instalado este (Ci20):
- Opencv
- Python
- Permissões de correção de porta serial
Usei a distro Debian 8 install &
download
Eu usei:
- Câmera de laptop antiga (reciclada)
- Módulo de alcance ultrassônico HC - SR04
- Bateria x2 3.7v 4000mah (laptop velho reciclado)
- x2 Servo
- conversor DC-DC
- Arduino nano
- Kit de base do robô
- x2 L298d
Para instalação, use os seguintes comandos no terminal.
Para atualizar o Linux.
sudo apt-get update # Busca a lista de atualizações disponíveis.
OpenCV. É a versão 2.4.9.1 que não está atualizada, mas funciona bem.
sudo apt-get install libopencv-dev python-opencv
Se você deseja compilar o OpenCV a partir do código-fonte, encontrei este tutorial.
Instale o PySerial.
sudo apt-get install python python-serial
Mudamos as permissões da porta serial, se você usou o USB ou um nativo.
sudo chown ci20:ci20 / dev / ttyUSB0 #Porta serial USB de Arduinosudo chown ci20:ci20 / dev / ttyS1 #Porta serial nativa em Ci20
Executa o script python (muda o zero se você tiver mais de uma fonte de vídeo, isso seleciona a fonte).
sudo python facetrackingcar.py 0
Para melhorar um pouco o desempenho, a imagem capturada não é exibida se você quiser ver, você deve pesquisar e descomentar essas linhas.
# cv.ShowImage ("result", img) # cv.NamedWindow ("result", 1) # cv.DestroyWindow ("result")
Você precisa ter o haarcascade_frontalface_alt.xml arquivo no mesmo diretório que o script.
Vídeo apenas para câmera de rastreamento no Windows
Vídeo de demonstração no Ci20
Feedback e melhorias são bem-vindos.
Código
- faceser.py
- Car.ino
- scanlinux.py
faceser.py Python
Script Python OpenCV face traking#! / Usr / bin / python "" "Este programa é uma demonstração para detecção de rosto e objeto usando recursos do tipo haar. O programa encontra rostos em uma imagem de câmera ou vídeo e exibe uma caixa vermelha em torno deles, em seguida, centraliza a webcam por meio de dois servos de modo que o rosto fique no centro da telaBaseado emidedetect.py no diretório de amostras OpenCV "" "import sysfrom optparse import OptionParserimport serialimport cv2.cv como cvimport time # Parâmetros para detecção de haar # Da API:# Os parâmetros padrão (scale_factor =2, min_neighbors =3, flags =0) são ajustados # para detecção de objetos precisa, porém lenta. Para uma operação mais rápida no vídeo real # imagens, as configurações são:# scale_factor =1.2, min_neighbors =2, flags =CV_HAAR_DO_CANNY_PRUNING, # min_size =>> servo.move (2, 90) ... # "move o servo # 2 a 90 graus "'' 'if (min_pwm <=ângulo <=max_pwm):ser.write (chr (255)) ser.write (chr (servo)) ser.write (chr (ângulo)) else:print" Servo ângulo deve ser um número inteiro entre 0 e 180. \ n "if __name__ =='__main__':ser =serial.Serial (port ='/ dev / ttyUSB0', baudrate =115200, tempo limite =1) # ser =serial.Serial (port ='/ dev / ttyS0', baudrate =115200, timeout =1) # ser =serial.Serial (port ='COM14', baudrate =115200, timeout =1) # parse cmd line options, setup Haar classifier parser =OptionParser (usage ="usage:% prog [options] [camera_index]") parser.add_option ("- c", "--cascade", action ="store", dest ="cascade", type ="str", help ="Arquivo em cascata Haar, 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] se input_name.isdigit ():capture =cv.CreateCameraCapture (int (input_name)) cv.SetCaptureProperty (capture, cv.CV_CAP_PROP_FRAME_WIDTH, 320) cv.SetCaptureProperty (captura, cv.CV_CAPTREP_FRAME) Precisamos de uma entrada de câmera! Especifique o índice da câmera, por exemplo 0 "sys.exit (0) # cv.NamedWindow (" result ", 1) if capture:frame_copy =None move (panGpioPin, servoPanPosition) move (tiltGpioPin, servoTiltPosition) enquanto True:start =time.time () frame =cv .QueryFrame (captura) se não for frame:cv.WaitKey (0) break se não 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, cascata) se midFace não for Nenhum:midFaceX =midFace [0] midFaceY =midFace [1] #Descubra se o componente X do rosto está à esquerda do meio da tela. if (midFaceX <(midScreenX - midScreenWindow)):#Atualize a variável de posição panorâmica para mover o servo para a direita. ServoPanPosition + =panStepSize print str (midFaceX) + ">" + str (midScreenX) + ":Pan Right:" + str (servoPanPosition) #Descubra se o X componente da face é para r direito do meio da tela. elif (midFaceX> (midScreenX + midScreenWindow)):#Atualize a variável de posição panorâmica para mover o servo para a esquerda. 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) #Descubra se o componente Y da face está abaixo do meio da tela. if (midFaceY <(midScreenY - midScreenWindow)):if (servoTiltPosition <=90):#Atualize a variável de posição de inclinação para diminuir o servo de inclinação. servoTiltPosition - =tiltStepSize print str (midFaceY) + ">" + str (midScreenY) + ":Tilt Down:" + str (servoTiltPosition) #Descubra se o componente Y do rosto está acima do meio da tela. elif (midFaceY> (midScreenY + midScreenWindow)):if (servoTiltPosition> =1):#Atualize a variável de posição de inclinação para aumentar o servo de inclinação. servoTiltPosition + =tiltStepSize imprimir str (midFaceY) + "<" + str (midScreenY) + ":Inclinação para cima:" + str (servoTiltPosition) start =1; fim =1; else:print str (midFaceY) + "~" + str (midScreenY) + ":" + str (servoTiltPosition) servoTiltPosition =min (servoTiltPosition, max_pwm) servoTiltPosition =max (servoTiltPosition, min_pwm) move (tiltGpiltPosition) elseTos:fim do tempo de medição end =time.time () + 0.1 var + =0.1 # obtendo o tempo decorrido time_elapsed =int (end - start + var) # imprimindo informações 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 de intervalo de atraso # cv.DestroyWindow ("result")
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 do usuário para servo e positionServo servoy; Servo servox; int x =90, prevX; int y =45, prevY; int userInput [3]; // entrada bruta do buffer serial, 3 bytesint startbyte; // inicia o byte, começa a ler inputint servo; // qual servo deve ser pulsado? int pos; // ângulo do 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 pela entrada serial (mín. 3 bytes no buffer) if (Serial.available ()> 2) {// Lê o primeiro byte startbyte =Serial.read (); // Se for realmente o byte inicial (255) ... if (byte inicial ==255) {// ... então obtenha os próximos dois bytes para (i =0; i <2; i ++) {userInput [i] =Serial.read (); } // Primeiro byte =servo para mover? servo =userInput [0]; // Segundo byte =qual posição? pos =userInput [1]; // Verificação de erro de pacote e recuperação if (pos ==255) {servo =255; } // Atribuir uma nova posição ao servo switch (servo) apropriado {case 1:servoy.write (pos); // move servo1 para 'pos' break; caso 2:servox.write (pos); alcance (pos); pausa; caso 3:varredura (45); digitalizar (65); pausa; padrão:break; }}}} void scan (int val) {while (Serial.available () ==0) {servoy.write (val); currentMillis longo sem sinal =millis (); if (currentMillis - previousMillis> =intervalo) {previousMillis =currentMillis; servox.write (pos); if (Estado ==BAIXO) {pos + =1; if (pos ==130) {State =HIGH; }} else {pos - =1; if (pos ==40) {State =LOW; pausa; }}}}} longa distancia () {longa duração, distância; digitalWrite (trigPin, LOW); // Adicionada esta linha delayMicroseconds (2); // Adicionada esta linha digitalWrite (trigPin, HIGH); atrasoMicrosegundos (10); // Adicionada esta linha digitalWrite (trigPin, LOW); duração =pulseIn (echoPin, HIGH); distância =(duração / 2) / 29,1; distância de retorno;} intervalo vazio (int pos) {if ((pos> =80) &(pos <=100)) {moves (); } else if ((pos> =100) &(pos <=180)) {left (); atraso (10); Pare(); } else if ((pos> =1) &(pos <=80)) {right (); atraso (10); Pare(); }} movimentos void () {longa distância, distância anterior; distância =distancia (); if (val <=80) {reverse (); atraso (50); Pare(); } else if (val> =140) {forward (); atraso (50); Pare(); } if (distance> =previusdistance) {val =(distance - previusdistance); } else if (distance <=previusdistance) {val =(previusdistance - distance); } previusdistance =distance;} void inicializado () {Serial.begin (115200); pinMode (MA_1, SAÍDA); pinMode (MA_2, OUTPUT); pinMode (MB_1, SAÍDA); pinMode (MB_2, SAÍDA); pinMode (MC_1, SAÍDA); pinMode (MC_2, SAÍDA); pinMode (MD_1, OUTPUT); pinMode (MD_2, SAÍDA); pinMode (trigPin, OUTPUT); pinMode (echoPin, INPUT); servox.attach (SERVOX_PIN); servoy.attach (SERVOY_PIN);} void forward () {digitalWrite (MA_1, HIGH); digitalWrite (MA_2, LOW); digitalWrite (MB_1, HIGH); digitalWrite (MB_2, LOW); digitalWrite (MC_1, HIGH); digitalWrite (MC_2, LOW); digitalWrite (MD_1, HIGH); digitalWrite (MD_2, LOW);} void reverse () {digitalWrite (MA_1, LOW); digitalWrite (MA_2, HIGH); digitalWrite (MB_1, BAIXO); digitalWrite (MB_2, HIGH); digitalWrite (MC_1, LOW); digitalWrite (MC_2, HIGH); digitalWrite (MD_1, LOW); digitalWrite (MD_2, HIGH);} void right () {digitalWrite (MA_1, LOW); digitalWrite (MA_2, HIGH); digitalWrite (MB_1, BAIXO); digitalWrite (MB_2, HIGH); digitalWrite (MC_1, HIGH); digitalWrite (MC_2, LOW); digitalWrite (MD_1, HIGH); digitalWrite (MD_2, BAIXO);} vazio à esquerda () {digitalWrite (MA_1, ALTO); digitalWrite (MA_2, LOW); digitalWrite (MB_1, HIGH); 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, BAIXO); 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, HIGH); digitalWrite (MB_1, HIGH); digitalWrite (MB_2, HIGH); digitalWrite (MC_1, HIGH); digitalWrite (MC_2, HIGH); digitalWrite (MD_1, HIGH); digitalWrite (MD_2, HIGH);}
scanlinux.py Python
Faça a varredura das portas seriais do Linux#! / usr / bin / env python "" "\ Procura por portas seriais. Variante específica do Linux que também inclui USB / Serialadapters.Part of pySerial (http://pyserial.sf.net) (C) 2009"" "import serialimport globdef scan ():" "" verifica as portas disponíveis. retorna uma lista de nomes de dispositivos. pvergain @ houx:~ / PDEV1V160_CodesRousseau / Soft / PC / test_boost / serialport / pyserial $ python scanlinux.py Portas encontradas :/ 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 "Portas encontradas:" para o nome em scan ():imprime o nome
Peças personalizadas e gabinetes
Python scrip OpenCV face traking e código Arduino FaceTrakingCar.rarEsquemas
Usando o arduino para controlar motores e servos, a pinagem pode variar.
Processo de manufatura
- Dados digitais Arduino
- DIY 37 LED Roulette Game
- ATtiny85 Mini Arcade:Snake
- Detector de alcance portátil
- MobBob:DIY Arduino Robot Controlado por Smartphone Android
- Robô de piano controlado por Arduino:PiBot
- Galvanoplastia com cobre
- NeoMatrix Arduino Pong
- Robô Omni-Direcional para Rastreamento de Pessoas
- Criador de sequência de luzes