« Color Code (PComp Midterm) | Main | ICM Final-Concept »

ICM Midterm

For my midterm project, I played with various video effects using a webcam as input. The movie below gives a general sense of the four effects (three mirror effects, and one motion tracking), though the video quality is truly terrible (sorry). To view the applet in action, paste the code below into Processing, and attach a webcam. Once set up, click 1, 2, 3, and 4 on the keyboard to scroll through the various effects.

Processing Code

To scroll through the different effects, type 1, 2, 3 or 4. Web cam required.

import processing.video.*;
Capture video;

int cellsize = 10; // Size of each cell in the grid
int cols, rows; // Number of columns and rows in our system
int mode; //variable to hold video selection
//code for motion detection
float sensitivity; // sensitivity is a percentage of pixels changed
boolean newFrame; // switch var for determining when a new frame is received
color[] prevFrame; // vars for holding the current and previous frames

void setup()
{
  size(400, 320);
  frameRate(30);
  smooth();
  background(0);
  //set up columns and rows for mirrors
  cols = width/cellsize;
  rows = height/cellsize;
  colorMode(RGB,255,255,255,100);
  //set up for motion detection
  sensitivity=0.4;
  newFrame=false;
  prevFrame=new color[width*height]; 
  
  // Using the default capture device
  video = new Capture(this, width, height, 20);
}

void captureEvent(Capture camera)
{
  camera.read();
  newFrame=true; //for motion detection
}

void draw()
{ 
  if (mode==1){
    circles();
  }
  else if (mode==2){
    star();
  }
  else if (mode==3){
    triangles();
  }
  else if (mode==4){
    motion();
  }
}

void keyPressed() //allows user to select one of four video modes
{
  if (key == '1' || key == '!') {
  mode=1;
  } 
  if (key == '2' || key == '@') {
  mode=2;
  }
  if (key == '3' || key == '#') {
  mode=3; 
  } 
  if (key == '4' || key == '$') {
  mode=4; 
  } 
}

void triangles(){
  background(255,140,0);
  cellsize=10;
  cols = width/cellsize;
  rows = height/cellsize;
  int t; //transparency
  // Begin loop for columns
  for ( int i = 0; i < cols;i++) {
    // Begin loop for rows
    for ( int j = 0; j < rows;j++) {
      
      // Where are we, pixel-wise?
      int x = i*cellsize;
      int y = j*cellsize;
      int loc = (video.width - x - 1) + y*video.width; // Reversing x to mirror the image
      //draw only yellow triangles
      float r=250;
      float g=250;
      float b = blue(video.pixels[loc]);
      if (b < 5){
        b=0;
        }
      else if (b<25 & b>=5){
        b=15;
        }
      else if (b<50 & b>=25){
        b=35;
        }
      else if (b<75 & b>=50){
        b=60;
        }
      else if (b<=115 & b>=90){
        b=100;
        }
      else if (b<=140 & b>=75){
        b=125;
        }
      else if (b<=165 & b>=140){
        b=150;
        }
      else{
        b=200;
      }
      //set transparency
      if (r+g+b<530){
        t=1;
      }
      else {
        t=100;
      }
      // Make a new color with an alpha component
      color c = color(r,g,b,t);
      
      // Code for drawing a single triangle
      // Using translate in order for rotation to work properly
      pushMatrix();
      translate(x+cellsize/2,y+cellsize/2);
      ellipseMode(CENTER);
      fill(c);
      noStroke();
      // Rects are larger than the cell for some overlap
      triangle(cellsize/2,0,cellsize,cellsize,0,cellsize);
      popMatrix();
    }
  }
}

void circles(){
  background(0);
  cellsize=12;
  cols = width/cellsize;
  rows = height/cellsize;
  // Begin loop for columns
  for ( int i = 0; i < cols;i++) {
    // Begin loop for rows
    for ( int j = 0; j < rows;j++) {
      
      // Where are we, pixel-wise?
      int x = i*cellsize;
      int y = j*cellsize;
      int loc = (video.width - x - 1) + y*video.width; // Reversing x to mirror the image
      
      float r = red(video.pixels[loc]);
      if (r < 50){
        r=0;
        }
      else if (r<100 & r>=50){
        r=50;
        }
      else if (r<150 & r>=100){
        r=100;
        }
      else if (r<200 & r>=150){
        r=150;
        }
      else if (r<=255 & r>=200){
        r=255;
        }
      float g = green(video.pixels[loc]);
      if (g < 50){
        g=0;
        }
      else if (g<100 & g>=50){
        g=50;
        }
      else if (g<150 & g>=100){
        g=100;
        }
      else if (g<200 & g>=150){
        g=150;
        }
      else if (g<=255 & g>=200){
        g=255;
        }
      float b = blue(video.pixels[loc]);
      if (b < 50){
        b=0;
        }
      else if (b<100 & b>=50){
        b=50;
        }
      else if (b<150 & b>=100){
        b=100;
        }
      else if (b<200 & b>=150){
        b=150;
        }
      else if (b<=255 & b>=200){
        b=255;
        }
      // Make a new color with an alpha component
      color c = color(r,g,b,75);
      
      // Code for drawing a single ellipse
      // Using translate in order for rotation to work properly
      pushMatrix();
      translate(x+cellsize/2,y+cellsize/2);
      ellipseMode(CENTER);
      fill(c);
      noStroke();
      // ellipses are larger than the cell for some overlap
      ellipse(0,0,cellsize-4,cellsize-4);
      popMatrix();
    }
  }
}

void star(){
 background(0);
  cellsize=14;
  cols = width/cellsize;
  rows = height/cellsize;
  // Begin loop for columns
  for ( int i = 0; i < cols;i++) {
    // Begin loop for rows
    for ( int j = 0; j < rows;j++) {
      
      // Where are we, pixel-wise?
      int x = i*cellsize;
      int y = j*cellsize;
      int loc = (video.width - x - 1) + y*video.width; // Reversing x to mirror the image
      
      float r = red(video.pixels[loc]);
      if (r < 25){
        r=0;
        }
      else if (r<75 & r>=25){
        r=50;
        }
      else if (r<125 & r>=75){
        r=100;
        }
      else if (r<200 & r>=125){
        r=175;
        }
      else if (r<=255 & r>=200){
        r=245;
        }
      float g = green(video.pixels[loc]);
      if (g < 25){
        g=0;
        }
      else if (g<75 & g>=25){
        g=50;
        }
      else if (g<200 & g>=75){
        g=100;
        }
      else if (g<200 & g>=125){
        g=175;
        }
      else if (g<=255 & g>=200){
        g=250;
        }
      float b = blue(video.pixels[loc]);
      if (b < 25){
        b=0;
        }
      else if (b<75 & b>=25){
        b=50;
        }
      else if (b<200 & b>=75){
        b=100;
        }
      else if (b<200 & b>=125){
        b=175;
        }
      else if (b<=255 & b>=200){
        b=255;
        }

      // Make a new color 
      color c = color(r,g,b,75);
      
      //draw a star
      // Using translate in order for rotation to work properly
      pushMatrix();
      translate(x+cellsize/2,y+cellsize/2);
      ellipseMode(CENTER);
      fill(c);
      noStroke();
      beginShape();
      vertex(7.5, 0);
      vertex(10, 5);
      vertex(15, 6);
      vertex(11, 10);
      vertex(12, 15);
      vertex(7.5, 12.5);
      vertex(2.8, 15);
      vertex(3.75, 10);
      vertex(0, 6);
      vertex(5, 5);
      vertex(7.5, 0);
      endShape();
      popMatrix();
    }
  }
}

void motion(){
  if(newFrame){
    newFrame=false;
    image(video,0,0); // update display with current frame
    for(int y=0; y<64-1; y++){ // loop through video in 60x80 grid
      for(int x=0; x<80-1; x++){
        int cxLoc=x*(width/80); // x position on grid
        int cyLoc=y*(height/64); // y position on grid
        if(motionTest(cxLoc,cyLoc,width/80,height/64)==true){
          float timer=random(5,10);
          fill(0,0,255,timer);
          noStroke();
          ellipse(cxLoc+random(0,7),cyLoc+random(0,7),5,5); //draw sparkles
          timer=random(10,15);
          fill(100,100,255,timer);
          ellipse(cxLoc+random(0,7),cyLoc+random(0,7),4,4); //draw sparkles
          timer=random(10,15);
          fill(200,200,255,timer);
          ellipse(cxLoc+random(0,7),cyLoc+random(0,7),3,3); //draw sparkles
          timer=random(15,20);
          fill(255,timer);
          ellipse(cxLoc+random(0,7),cyLoc+random(0,7),2,2); //draw sparkles
        }
      }
    }
  }
}
// this is used to determine when the person is moving for the motion effect
boolean motionTest(int srcX,int srcY,int tw, int th){
    int dc=0; // counter to track number of differences
    color newPixel; 
    for(int y=0;y23) dc++; 
        else if(abs(green(newPixel)-green(prevFrame[srcPos]))>23) dc++;
        else if(abs(blue(newPixel)-blue(prevFrame[srcPos]))>23) dc++;
        prevFrame[srcPos]=newPixel; // update prevFrame w/ current pixel clr
      }
    }
    // test to see if number of difference is 'significant'
    if(dc>(sensitivity*(tw*th))){  
      return true;
    }
    else{
      return false;
    }
  } 

TrackBack

TrackBack URL for this entry:
http://itp.nyu.edu/~km63/cgi-bin/mt/mt-tb.cgi/13

Comments

Thanks for posting the code. I'm going to play around with it to see what I can get.

Thanks,
Chris

My pleasure Chris! Post a link to your results here if you feel like it--I'd love to see.
-Kate

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)