Controlling a camera using another camera

Using Arduino, Processing, a webcam and a servo motor, a camera makes move another camera.

This is the last project for the physical computing class at RIT that Ben and I finished last monday. It doesn»t mean that I»m not going to post more little experiments here, but the course is over and for sure that the amount of posts will decrease.

This little propject is about building a system in which a camera controls another camera. Actually, one camera tracks the movement in from of it, and depending on where it takes place, it makes move the other camera in one or other direction.

So what we have here is two cameras. One camera is the control camera (the camera that is in the laptop), and the other is the «slave» camera. The «slave camera» has a servo motor and the control camera moves this motor depending on what is in front of it, or if the camera detects movement on the right or left side of the screen.

Controlling a cam with another cam from berio on Vimeo.

Some pictures

Arduino code:

 
/*
Controlling a camera using another camera from Processing.
Arduino Version.

Based on Tom Igoe"s example:
http://itp.nyu.edu/physcomp/Labs/Servo

by Berio Molina
Created 10 May 2008
*/

int servoPin = 9; // Control pin for servo motor
int minPulse = 500; // Minimum servo position
int maxPulse = 2500; // Maximum servo position
int pulse = 1000; // Amount to pulse the servo

long lastPulse = 0; // the time in milliseconds of the last pulse
int refreshTime = 20; // the time needed in between pulses

int incomingByte = 0;

void setup() {
pinMode(servoPin, OUTPUT); // Set servo pin as an output pin
Serial.begin(9600);

// Set the motor position value to the middle
pulse = (maxPulse-minPulse)/2;
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulse); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
}

void loop() {
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();

if(incomingByte == 1 ){ // 1 = value that is comming from processing
if(pulse>minPulse){
pulse -= 4;
}
}
if(incomingByte == 2){ // 2 = value that is comming from processing
if(pulse pulse += 4;
}
}

// pulse the servo again if rhe refresh time (20 ms) have passed:
if (millis() - lastPulse >= refreshTime) {
digitalWrite(servoPin, HIGH); // Turn the motor on
delayMicroseconds(pulse); // Length of the pulse sets the motor position
digitalWrite(servoPin, LOW); // Turn the motor off
lastPulse = millis(); // save the time of the last pulse
}
}
}

Processing code

 
// libraries
import JMyron.*;
import processing.video.*;
import processing.serial.*;

boolean hijack = true;
boolean firstRun = true;
float sumAllRect = 0;
float countAllRect = 0;
float averageRect = 0;
Capture cameraMotor; // camera servo motor
JMyron cameraTrack;//a camera object

Serial myPort;

// Needed on an apple mac?
import quicktime.*;

void setup(){
size(400,300);
println(Serial.list());
myPort = new Serial(this, Serial.list()[0], 9600);
println(Capture.list());
cameraMotor = new Capture(this, width, height, Capture.list()[3], 30);

// initialise qt - on a mac only?
try{
QTSession.open();
}
catch (Exception e) {
e.printStackTrace();
}

cameraTrack = new JMyron();//make a new instance of the object
cameraTrack.start(width,height);//start a capture
cameraTrack.findGlobs(1);//enable the intelligence
cameraTrack.trackColor(255,255,255,256*3-100);
cameraTrack.update();
cameraTrack.adaptivity(10);
cameraTrack.adapt();

println("Myron " + cameraTrack.version());
println("Tolerance " + int(256*3-100));
}

void draw(){
background(255);

cameraTrack.update();//update the camera view
// drawCamera();
if(cameraMotor.available()){
cameraMotor.read();
}
image(cameraMotor, 0, 0);

noFill();
int[][] a;

//find center points of globs and sum the location
// of all of them to create an average. Then draw a black line
// to visualize where the average movement is.
a = cameraTrack.globCenters();
if(a.length>0){
for(int i=0;i int[] p = a[i];
sumAllRect = sumAllRect + p[0];
countAllRect ++;
}

averageRect = sumAllRect/countAllRect;

if(averageRect != 0){
if(averageRect >= 150){
myPort.write(1); // send 1 to the serial port
println("right");
}else{
myPort.write(2); // send 2 to the serial port
println("left");
}
println(sumAllRect/countAllRect);
}
stroke(0, 90);
strokeWeight(10);
line(width-averageRect, 0, width-averageRect, height);
sumAllRect = 0;
countAllRect = 0;
}
}

// Called every time a new frame is available to read
void movieEvent(Movie mov) {
mov.read();
}

public void stop(){
cameraTrack.stop();//stop the object
super.stop();
}

Download: