Bouw Een Real-Time Gezichtsvolgsysteem Met Arduino & OpenCV
Onderdelen en benodigdheden
| Onderdeel | Aantal |
|---|---|
| Arduino UNO | 1 |
| Webcam | 1 |
| Micro servos | 2 |
| Pan-Tilt kit | 1 |
| Breadboard (standaard) | 1 |
Apps en online diensten
- Python 2.7
- OpenCV
Over dit project
In een eerdere tutorial deelde ik hoe je kunt communiceren tussen Arduino en Python met de 'pyserial'-module en een LED kunt besturen. Als je dat niet gezien hebt, bekijk het hier: COMMUNICATIE TUSSEN ARDUINO & PYTHON!
En hoe je de kleur van een object kunt detecteren en volgen op scherm, bekijk dat hier: KLEURDETECTIE MET OPENCV EN PYTHON.
In deze tutorial laat ik je zien hoe je gezichten kunt volgen met Arduino en Python en de camera het gezicht laat volgen. Dit klinkt misschien moeilijk, maar vertrouw me, het is het niet. Je hebt alleen basiskennis van Arduino en Python nodig.
Laten we beginnen...
Stap 1: Wat je nodig hebt
De vereisten zijn minimaal. Hier is de lijst met alles wat je nodig hebt:
Hardwarevereisten:
- Arduino UNO (andere boards zijn ook mogelijk)
- Webcam (Mini-webcam)
- Servos x 2 (ik gebruik micro servos, maar standaard servos werken ook)
- Breadboard (voor prototyping)
- Servo Pan-Tilt Kit (je kunt er zelf een bouwen als je wilt)
Softwarevereisten:
- Python 2.7 (moet geïnstalleerd zijn, Linux OS heeft het meestal voorgeïnstalleerd)
- OpenCV (los te downloaden of te installeren met 'pip install', verder uitgelegd)
- pyserial (kan geïnstalleerd worden met pip)
- numpy
- Haarcascade
Als alles verzameld is, kunnen we doorgaan naar de installatiestap...
Stap 2: Python-omgeving instellen
Python installeren:
Eerst hebben we Python 2.7 nodig. Download en installeer Python 2.7.14. Om te controleren of het correct geïnstalleerd is: Ga naar Windows Zoeken >> Typ "IDLE" >> Enter. Er zou een Python Shell moeten verschijnen.
OF
In zoeken typ 'CMD' en druk enter om de opdrachtprompt te openen. In CMD typ >> python en enter, de Python-interface zou moeten verschijnen.
Als je een foutziet in CMD, paniek niet, je moet waarschijnlijk de omgevingsvariabele instellen. Je kunt deze tutorial hier volgen om de omgevingsvariabele in te stellen.
'pyserial', 'OpenCV' en 'numpy' installeren in Python:
We gebruiken pip install voor deze modules:
Open CMD en typ de volgende commando's:
> pip install serial
> pip install opencv-python
> pip install numpy
Deze commando's installeren de benodigde modules. Nu kunnen we naar het codergedeelte...
Stap 3: Python-script
Voordat we beginnen met coderen, maak eerst een nieuwe map aan, want alle code moet in dezelfde map staan. Maak een nieuwe map, geef het een naam, en download de 'Haarcascade' hieronder en plaats het in de map.
Open nu Kladblok en schrijf het onderstaande script, bewaar het als 'face.py' in dezelfde map als haarcascade. (Je kunt de code downloaden, ik heb het bestand hieronder gegeven):
# Importeer alle benodigde modules
import numpy as np
import serial
import time
import sys
import cv2
# Stel communicatiepad in voor arduino (vervang 'COM5' door de poort waar je arduino op aangesloten is)
arduino = serial.Serial('COM5', 9600)
time.sleep(2)
print("Verbonden met arduino...")
# Importeer de Haarcascade voor gezichtsdetectie
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# Videostream van webcam vastleggen
cap = cv2.VideoCapture(0)
# Lees vastgelegde afbeelding, converteer naar grijswaarden en vind gezichten
while 1:
ret, img = cap.read()
cv2.resizeWindow('img', 500, 500)
cv2.line(img, (500, 250), (0, 250), (0, 255, 0), 1)
cv2.line(img, (250, 0), (250, 500), (0, 255, 0), 1)
cv2.circle(img, (250, 250), 5, (255, 255, 255), -1)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
faces = face_cascade.detectMultiScale(gray, 1.3)
# Detecteer gezicht en teken rechthoek eromheen
for (x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 5)
roi_gray = gray[y:y+h, x:x+w]
roi_color = img[y:y+h, x:x+w]
arr = {y:y+h, x:x+w}
print(arr)
print('X :' + str(x))
print('Y :' + str(y))
print('x+w :' + str(x+w))
print('y+h :' + str(y+h))
# Midden van ROI (rechthoek)
xx = int(x + (x + h)) / 2
yy = int(y + (y + w)) / 2
print(xx)
print(yy)
center = (xx, yy)
# Data naar arduino sturen
print("Midden van rechthoek is :", center)
data = "X{0:d}Y{1:d}Z".format(xx, yy)
print("output = '" + data + "'")
arduino.write(data)
# Stream tonen
cv2.imshow('img', img)
# Druk 'Esc' om te stoppen
k = cv2.waitKey(30) & 0xff
if k == 27:
break
Eenmaal gedaan, gaan we de code voor Arduino schrijven...
haarcascade_frontalface_default.xml face.pyStap 4: Arduino-code
Nu het Python-script klaar is, hebben we een Arduino-sketch nodig om de servo te besturen. Zie de code hieronder, plak het in de Arduino IDE en bewaar het als 'servo.ino' in dezelfde map als face.py en haarcascade. Upload de code en ga verder met de volgende stap voor de verbindingen.
(Downloadbaar bestand hieronder gegeven.)
#include <Servo.h>
Servo servoVer; // Verticale servo
Servo servoHor; // Horizontale servo
int x;
int y;
int prevX;
int prevY;
void setup() {
Serial.begin(9600);
servoVer.attach(5); // Verticale servo op pin 5
servoHor.attach(6); // Horizontale servo op pin 6
servoVer.write(90);
servoHor.write(90);
}
void Pos() {
if (prevX != x || prevY != y) {
int servoX = map(x, 600, 0, 70, 179);
int servoY = map(y, 450, 0, 179, 95);
servoX = min(servoX, 179);
servoX = max(servoX, 70);
servoY = min(servoY, 179);
servoY = max(servoY, 95);
servoHor.write(servoX);
servoVer.write(servoY);
}
}
void loop() {
if (Serial.available() > 0) {
if (Serial.read() == 'X') {
x = Serial.parseInt();
if (Serial.read() == 'Y') {
y = Serial.parseInt();
Pos();
}
}
while (Serial.available() > 0) {
Serial.read(); // Buffer leegmaken
}
}
}
servo.ino
Stap 5: Pan-Tilt mechanisme
Ik gebruikte een kant-en-klaar kit voor de Pan-Tilt. Als je wilt kun je er zelf een maken van hout/kunststof of zelfs 3D-printen.
Die ik gebruikte is goedkoop en heel makkelijk te monteren. Als je instructies wilt, vind je ze hier.
Stap 6: Verbindingen maken
De schakeling is vrij simpel. Sluit gewoon twee servos aan op de Arduino.
- Verticaal naar pin 5
- Horizontaal naar pin 6
- Voeding naar +5V
- Massa naar GND
Controleer het schakelingsschema voor referentie.
Stap 7: Testen
- Na alles klaar is, test of het werkt. Zorg er eerst voor dat de servos correct aan de Arduino zijn aangesloten en de sketch geüpload is.
- Na het uploaden, sluit de IDE zodat de poort vrij is voor Python.
- Open 'face.py' met Python IDLE en druk 'F5' om de code te draaien. Het duurt even voordat de verbinding met Arduino gemaakt is, en dan zou je een venster moeten zien met de webcam-stream. De code detecteert je gezicht en de servos volgen het.
- De servo zou moeten bewegen als je het object beweegt. Nu de camera aan de servos bevestigen zodat hij mee beweegt.
Hopelijk vind je het leuk en leer je er iets van.
Dank je!
Code
servo.ino (Arduino)
Fout bij openen bestand.
Code snippet #2 (Plain text)
#import all the required modules import numpy as np import serial import time import sys import cv2 #Setup Communication path for arduino (In place of 'COM5' put the port to which your arduino is connected) arduino = serial.Serial('COM5', 9600) time.sleep(2) print("Connected to arduino...") #importing the Haarcascade for face detection face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') #To capture the video stream from webcam. cap = cv2.VideoCapture(0) #Read the captured image, convert it to Gray image and find faces while 1: ret, img = cap.read() cv2.resizeWindow('img', 500,500) cv2.line(img,(500,250),(0,250),(0,255,0),1) cv2.line(img,(250,0),(250,500),(0,255,0),1) cv2.circle(img, (250, 250), 5, (255, 255, 255), -1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, 1.3) #detect the face and make a rectangle around it. for (x,y,w,h) in faces: cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),5) roi_gray = gray[y:y+h, x:x+w] roi_color = img[y:y+h, x:x+w] arr = {y:y+h, x:x+w} print (arr) print ('X :' +str(x)) print ('Y :'+str(y)) print ('x+w :' +str(x+w)) print ('y+h :' +str(y+h)) # Center of roi (Rectangle) xx = int(x+(x+h))/2 yy = int(y+(y+w))/2 print (xx) print (yy) center = (xx,yy) # sending data to arduino print("Center of Rectangle is :", center) data = "X{0:d}Y{1:d}Z".format(xx, yy) print ("output = '" +data+ "'") arduino.write(data) #Display the stream. cv2.imshow('img',img) #Hit 'Esc' to terminate execution k = cv2.waitKey(30) & 0xff if k == 27: break
Code snippet #3 (Plain text)
#include<servo.h> Servo servoVer; //Vertical Servo Servo servoHor; //Horizontal Servo int x; int y; int prevX; int prevY; void setup() { Serial.begin(9600); servoVer.attach(5); //Attach Vertical Servo to Pin 5 servoHor.attach(6); //Attach Horizontal Servo to Pin 6 servoVer.write(90); servoHor.write(90); } void Pos() { if(prevX != x || prevY != y) { int servoX = map(x, 600, 0, 70, 179); int servoY = map(y, 450, 0, 179, 95); servoX = min(servoX, 179); servoX = max(servoX, 70); servoY = min(servoY, 179); servoY = max(servoY, 95); servoHor.write(servoX); servoVer.write(servoY); } } void loop() { if(Serial.available() > 0) { if(Serial.read() == 'X') { x = Serial.parseInt(); if(Serial.read() == 'Y') { y = Serial.parseInt(); Pos(); } } while(Serial.available() > 0) { Serial.read(); } } }
Productieproces
- Een externe temperatuursensor bouwen met Raspberry Pi en Python – Stap-voor-stap handleiding
- Real-time Gezichtsherkenning op Raspberry Pi – Complete Gids
- Geautomatiseerde Visuele Object-tracking met Raspberry Pi en OpenCV
- Een DTMF-decoder bouwen met alleen een Arduino – Geen extra IC's nodig
- Bouw een indrukwekkend monitor Ambilight-systeem met Arduino
- Betrouwbaar Arduino RFID Aanwezigheidssysteem Aangedreven door Python
- Bouw een Ultrasonische Zweefapparaat met Arduino – Stap-voor-stap Handleiding
- Een slimme voltmeter bouwen met Arduino en smartphone – Eenvoudig DIY-project
- Real-time IoT hartslagmonitor met Arduino en MAX30100
- Arduino Uno WiFi Webserver: LED aan/uit schakelen via browser
- IoT-Thermometer Bouwen met Python: Complete Handleiding