天问

Mathematica+Arduino 摄像头检测人脸并跟随

http://bbs.makercollider.com/?/article/27

通过USB摄像头获取图像,如果检测到人脸将计算出中心坐标,把坐标通过串口发送给Arduino,算出人脸坐标偏离画面中心点的距离,然后根据这个偏离值驱动舵机带动摄像头修正指向,从而可以跟随人脸移动。

 

软件
Mathematica 10/11
Arduino IDE
硬件
Arduino开发板
USB摄像头
9g舵机
舵机云台

 

连接线若干

 

连接
把摄像头固定在舵机云台上,在Arduino开发板上插上IO传感器扩展板,舵机接在传感器扩展板的第9个数字引脚上。
注意:
如果选用的是大功率的云台和舵机,需要为舵机独立供电。
本文使用的云台为一个自由度(水平移动),知道了原理后扩展为两个自由度也很简单(水平+垂直)。

883214db04809760921505f5bf73ea4b.jpg (188.04 KB, 下载次数: 0)

下载附件  保存到相册

2016-12-6 15:13 上传

 

演示

 

摄像头追踪人脸.gif (1.8 MB, 下载次数: 0)

下载附件  保存到相册

2016-12-6 14:59 上传

 

Mathematica 代码
[AppleScript] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
$ImagingDevice = $ImagingDevices[[2]];
dev = DeviceOpen["Serial", "COM3"]
Dynamic[
 i = CurrentImage[];
 boxes = FindFaces[i];
 If[boxes =!= {},
  {X, Y} = Round[Mean @@ boxes];
  Column@
   {
    HighlightImage[i, Circle[{X, Y}, 50], ImageSize -> {320, 240}],
    DeviceWrite[dev, ToString[X]]
    },
  i]
 ]

 

Arduino 代码
[C] 纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#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);
  }
}
博客地址:http://blog.yoqi.me/?p=1370
扫我捐助哦
喜欢 1

这篇文章还没有评论

发表评论