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;y| 23) 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;
}
}
|