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 autonome de suivi de visage avec Arduino Nano et OpenCV

Composants et fournitures

ComposantQuantité
Creator Ci20 (carte embarquée Linux)1
Double pont en H L298 (SparkFun)1
Batterie Li-Ion 1000 mAh1
Servomoteurs Tower Pro MG996R2
Caméra (générique, ex: vieille webcam récupérée)1
Kit base robot GoPiGo (Dexter Industries)1
Arduino Nano R31
Capteur ultrasons HC-SR041

Applications et services en ligne

À propos de ce projet

Un robot qui suit votre visage : si vous vous éloignez, il vient vers vous !

Prérequis logiciels (sur Ci20, Debian 8)

Matériel utilisé (partiellement récupéré)

Lancement

Placez haarcascade_frontalface_alt.xml dans le même dossier que le script Python. Puis :

sudo python facetrackingcar.py 0

(Remplacez 0 par l'index de votre caméra si plusieurs sources vidéo).

Pour gagner en performance, l'image capturée n'est pas affichée. Pour la voir, décommentez :

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

Code

faceser.py (Python – OpenCV suivi visage + envoi commandes série)

#!/usr/bin/python
""" Démonstration détection visage Haar + asservissement 2 servos pour centrer le visage. """
import sys, serial, cv2.cv as cv, time
from optparse import OptionParser

# Paramètres détection Haar
min_size = (20, 20)
image_scale = 2
haar_scale = 1.2
min_neighbors = 2
haar_flags = cv.CV_HAAR_DO_CANNY_PRUNING

# Servos
max_pwm = 180; min_pwm = 1
midScreenWindow = 20   # zone morte centre écran (pixels)
panStepSize = 1        # pas pan (degrés)
tiltStepSize = 1       # pas tilt (degrés)
servoPanPosition = 90  # position initiale pan (X)
servoTiltPosition = 45 # position initiale tilt (Y)
panGpioPin = 2         # ID servo pan côté Arduino (pas numéro broche)
tiltGpioPin = 1        # ID servo tilt côté Arduino

def detect_and_draw(img, cascade):
    gray = cv.CreateImage((img.width, img.height), 8, 1)
    small_img = cv.CreateImage((cv.Round(img.width / image_scale),
                                cv.Round(img.height / image_scale)), 8, 1)
    cv.CvtColor(img, gray, cv.CV_BGR2GRAY)
    cv.Resize(gray, small_img, cv.CV_INTER_LINEAR)
    cv.EqualizeHist(small_img, small_img)
    midFace = None
    if cascade:
        faces = cv.HaarDetectObjects(small_img, cascade, cv.CreateMemStorage(0),
                                     haar_scale, min_neighbors, haar_flags, min_size)
        if faces:
            for ((x, y, w, h), n) in faces:
                pt1 = (int(x * image_scale), int(y * image_scale))
                pt2 = (int((x + w) * image_scale), int((y + h) * image_scale))
                cv.Rectangle(img, pt1, pt2, cv.RGB(255, 0, 0), 3, 8, 0)
                x1, x2, y1, y2 = pt1[0], pt2[0], pt1[1], pt2[1]
                midFace = (x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2)
    return midFace

def move(servo, angle):
    if min_pwm <= angle <= max_pwm:
        ser.write(chr(255))
        ser.write(chr(servo))
        ser.write(chr(angle))
    else:
        print("Angle servo doit être entre 0 et 180.")

if __name__ == '__main__':
    ser = serial.Serial(port='/dev/ttyUSB0', baudrate=115200, timeout=1)
    parser = OptionParser(usage="usage: %prog [options] [camera_index]")
    parser.add_option("-c", "--cascade", dest="cascade", 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 = args[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)
    else:
        print("Spécifiez l'index caméra, ex: 0"); sys.exit(0)
    
    move(panGpioPin, servoPanPosition)
    move(tiltGpioPin, servoTiltPosition)
    
    while True:
        frame = cv.QueryFrame(capture)
        if not frame: break
        # ... (traitement image, détection visage, calcul erreur centre, mise à jour servos)
        # Code complet dans le fichier original.
        if cv.WaitKey(1) >= 0: break

Car.ino (Arduino – contrôle moteurs + servos + ultrasons)

#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

Servo servoy, servox;
int x = 90, prevX, y = 45, prevY;
int userInput[3], startbyte, servo, pos, i, State = LOW;
unsigned long previousMillis = 0, val = 100;
const long interval = 100;
bool scana = false;

void setup() {
  inicializate();
}

void loop() {
  if (Serial.available() > 2) {
    startbyte = Serial.read();
    if (startbyte == 255) {
      for (i = 0; i < 2; i++) userInput[i] = Serial.read();
      servo = userInput[0]; pos = userInput[1];
      if (pos == 255) servo = 255;
      switch (servo) {
        case 1: servoy.write(pos); break;
        case 2: servox.write(pos); range(pos); break;
        case 3: scan(45); scan(65); break;
      }
    }
  }
}

void scan(int val) {
  while (Serial.available() == 0) {
    servoy.write(val);
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      servox.write(pos);
      if (State == LOW) { pos++; if (pos == 130) State = HIGH; }
      else { pos--; if (pos == 40) { State = LOW; break; } }
    }
  }
}

long distancia() {
  digitalWrite(trigPin, LOW); delayMicroseconds(2);
  digitalWrite(trigPin, HIGH); delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  long duration = pulseIn(echoPin, HIGH);
  return (duration / 2) / 29.1;
}

void range(int pos) {
  if (pos >= 80 && pos <= 100) moves();
  else if (pos >= 100 && pos <= 180) { left(); delay(10); Stop(); }
  else if (pos >= 1 && pos <= 80) { right(); delay(10); Stop(); }
}

void moves() {
  long distance = distancia();
  if (val <= 80) { reverse(); delay(50); Stop(); }
  else if (val >= 140) { forward(); delay(50); Stop(); }
  // ... logique suivi distance
}

void inicializate() {
  Serial.begin(115200);
  // Config broches moteurs, servos, ultrasons
  servox.attach(SERVOX_PIN); servoy.attach(SERVOY_PIN);
}

void forward()  { /* Moteurs avant */ }
void reverse()  { /* Moteurs arrière */ }
void right()    { /* Rotation droite */ }
void left()     { /* Rotation gauche */ }
void Stop()     { /* Arrêt */ }
void StopH()    { /* Freinage (toutes broches HIGH) */ }

scanlinux.py (Python – détection ports série Linux)

#!/usr/bin/env python
import serial, glob
def scan():
    return glob.glob('/dev/ttyS*') + glob.glob('/dev/ttyUSB*') + \
           glob.glob('/dev/ttyACM*') + glob.glob('/dev/serial/by-id/*')
if __name__ == '__main__':
    print("Found ports:")
    for name in scan(): print(name)

Pièces personnalisées et boîtiers

Script Python OpenCV + code Arduino : FaceTrakingCar.rar

Schémas

Contrôle moteurs et servos par Arduino (brochage variable).

Voiture robot autonome de suivi de visage avec Arduino Nano et OpenCV

Processus de fabrication

  1. Dé numérique Arduino sur écran LCD 16x2 – Générateur aléatoire à bouton poussoir
  2. Créer votre propre jeu de roulette à 37 LED avec Arduino Nano
  3. ATtiny85 Mini Arcade : Snake – Construire une console de jeu portable OLED
  4. Détecteur de distance portable – Kit DIY Arduino Nano avec HC-SR04, alimentation 18650 et boîtier imprimé 3D
  5. MobBob : Construisez votre propre robot Arduino, contrôlé via smartphone Android
  6. PiBot : Robot pianiste Arduino pour performance musicale de précision
  7. Projet de galvanoplastie au cuivre : Construisez un système intelligent avec Arduino UNO
  8. Jeu Pong sur Matrice NeoPixel avec Arduino Nano
  9. Robot Omnidirectionnel pour Suivi de Personne en Sécurité