Controlling a camera using another camera

Controlling a camera using another camera

<article99|logo>

<article99|logosdereita>

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.

JPEG - 28.1 KB

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

JPEG - 62.2 KB
JPEG - 33.5 KB
JPEG - 20.4 KB
JPEG - 27.3 KB


JPEG - 47.9 KB

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<maxPulse){
       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<a.length;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:

Zip - 3.2 KB