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

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

 

软件

Mathematica 10/11

Arduino IDE

 

硬件

Arduino开发板

USB摄像头

9g舵机

舵机云台

连接线若干

 

连接

把摄像头固定在舵机云台上,在Arduino开发板上插上IO传感器扩展板,舵机接在传感器扩展板的第9个数字引脚上。

 

注意:

*如果选用的是大功率的云台和舵机,需要为舵机独立供电。

*本文使用的云台为一个自由度(水平移动),知道了原理后扩展为两个自由度也很简单(水平+垂直)。

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

 

演示

 

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

 

Mathematica 代码

$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代码

#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);

 

  }

}