通过USB摄像头获取图像,如果检测到人脸将计算出中心坐标,把坐标通过串口发送给Arduino,算出人脸坐标偏离画面中心点的距离,然后根据这个偏离值驱动舵机带动摄像头修正指向,从而可以跟随人脸移动。
软件 Mathematica 10/11 Arduino IDE
硬件 Arduino开发板 USB摄像头 9g舵机 舵机云台
连接线若干
连接 把摄像头固定在舵机云台上,在Arduino开发板上插上IO传感器扩展板,舵机接在传感器扩展板的第9个数字引脚上。 注意: 如果选用的是大功率的云台和舵机,需要为舵机独立供电。 本文使用的云台为一个自由度(水平移动),知道了原理后扩展为两个自由度也很简单(水平+垂直)。
演示
Mathematica 代码
- $ImagingDevice = $ImagingDevices[[2]];
-
- dev = DeviceOpen["Serial", "COM3"]
-
- Dynamic[
- i = CurrentImage[];
- boxes = FindFaces;
- If[boxes =!= {},
- {X, Y} = Round[Mean @@ boxes];
- Column@
- {
- HighlightImage[i, Circle[{X, Y}, 50], ImageSize -> {320, 240}],
- DeviceWrite[dev, ToString[X]]
- },
- i]
- ]
复制代码
Arduino 代码
- #include <Servo.h>
-
- #define servomaxx 180 // max degree servo horizontal (x) can turn
- #define screenmaxx 320 // max screen horizontal (x)resolution
- #define screenmaxy 240 // max screen vertical (y) resolution
- #define servocenterx 90 // center po#define of x servo
- #define servopinx 9 // digital pin for servo x
- #define baudrate 9600 // com port speed. Must match your setting
- #define distancex 2 // x servo rotation steps
-
- int valx = 0; // store x data from serial port
- int posx = 0;
- int incx = 10; // significant increments of horizontal (x) camera movement
-
- Servo servox;
-
- void setup() {
- Serial.begin(baudrate); // connect to the serial port
- Serial.setTimeout(20);
- Serial.println("Starting Cam-servo Face tracker");
-
- pinMode(servopinx, OUTPUT); // declare the LED's pin as output
-
- servox.attach(servopinx);
-
- // center servos
- servox.write(servocenterx);
- delay(200);
- }
-
-
- void loop () {
- while (Serial.available() <= 0); // wait for incoming serial data
- if (Serial.available() >= 1)
- {
- // get X axis 2-byte integer from serial
- valx = Serial.parseInt();
-
- // read last servos positions
- posx = servox.read();
-
- //Find out if the X component of the face is to the left of the middle of the screen.
- if (valx < (screenmaxx / 2 - incx)) {
- if ( posx >= incx ) posx += distancex; //Update the pan position variable to move the servo to the left.
- }
- //Find out if the X component of the face is to the right of the middle of the screen.
- else if (valx > screenmaxx / 2 + incx) {
- if (posx <= servomaxx - incx) posx -= distancex; //Update the pan position variable to move the servo to the right.
- }
-
- // Servos will rotate accordingly
- servox.write(posx);
-
- }
- }
复制代码
|