Brightness Tracking to PDF Trace

// Brightness Tracking + PDF
// Combines the Prightness Tracking demo 
// with the PDF Pause/Record demo.
// see http://www.processing.org/reference/libraries/pdf/index.html
 
import processing.video.*;
import processing.pdf.*;
 
Capture video;
boolean recording;
PGraphicsPDF pdf;
int pBrightestX;
int pBrightestY;
 
 
void setup() {
  size(640, 480); // Change size to 320 x 240 if too slow at 640 x 480
  // Uses the default video input, see the reference if this causes an error
  video = new Capture(this, width, height, 30);
  noStroke();
  smooth();
 
  recording = false;
  pdf = (PGraphicsPDF) createGraphics(width, height, PDF, "pause-resume.pdf");
 
}
 
void draw() {
 
 
  if (video.available()) {
    video.read();
    //image(video, 0, 0, width, height); // Draw the webcam video onto the screen
    int brightestX = 0; // X-coordinate of the brightest video pixel
    int brightestY = 0; // Y-coordinate of the brightest video pixel
    float brightestValue = 0; // Brightness of the brightest video pixel
    // Search for the brightest pixel: For each row of pixels in the video image and
    // for each pixel in the yth row, compute each pixel's index in the video
    video.loadPixels();
    int index = 0;
    for (int y = 0; y < video.height; y++) {
      for (int x = 0; x < video.width; x++) {
        // Get the color stored in the pixel
        int pixelValue = video.pixels[index];
        // Determine the brightness of the pixel
        float pixelBrightness = brightness(pixelValue);
        // If that value is brighter than any previous, then store the
        // brightness of that pixel, as well as its (x,y) location
        if (pixelBrightness > brightestValue) {
          brightestValue = pixelBrightness;
          brightestY = y;
          brightestX = x;
        }
        index++;
      }
    }
    // draw a line to trace
    line(pBrightestX, pBrightestY, brightestX, brightestY);
 
    pBrightestX = brightestX;
    pBrightestY = brightestY;
 
  }
 
 
 
 
}
 
void keyPressed() {
  if (key == 'r') {
    if (recording) {
      endRecord();
      println("Recording stopped.");
      recording = false;
    } else {
      beginRecord(pdf);
      println("Recording started.");
      recording = true;
    }
  } else if (key == 'q') {
    if (recording) {
      endRecord();
    }
    exit();
  }  
}

Contour Traced on Thresholded Video

// Thresholded video image; 
// Contour traced for the first white blob
import processing.video.*;
 
color black = color(0);
color white = color(255);
int numPixels;
Capture video;
 
int MAX_CHAIN_LEN = 10000;
int chainLength = 0;
Point2d firstPixel;
Point2d chain[];
 
void setup() {
  size(640, 480); // Change size to 320 x 240 if too slow at 640 x 480
  strokeWeight(5);
  // Uses the default video input, see the reference if this causes an error
  video = new Capture(this, width, height, 24);
  numPixels = video.width * video.height;
  noCursor();
  smooth();
 
  firstPixel = new Point2d();
  chain = new Point2d[MAX_CHAIN_LEN];
  for (int i=0; i<MAX_CHAIN_LEN; i++){
    chain[i] = new Point2d();
  }  
}
 
void draw() {
  if (video.available()) {
    video.read();
    video.loadPixels();
    int threshold = 127; // Set the threshold value
    float pixelBrightness; // Declare variable to store a pixel's color
    // Turn each pixel in the video frame black or white depending on its brightness
    loadPixels();
    for (int i = 0; i < numPixels; i++) {
      pixelBrightness = brightness(video.pixels[i]);
      if (pixelBrightness > threshold) { // If the pixel is brighter than the
        pixels[i] = white; // threshold value, make it white
      } 
      else { // Otherwise,
        pixels[i] = black; // make it black
      }
    }
    updatePixels();
 
 
    //-------------------------------------
    // CHAIN CODE (Contour Tracing)
    findFirstPixel();
    chain8 (firstPixel.x, firstPixel.y);
 
    strokeWeight(3);
    stroke(255,0,0); 
    noFill();
    beginShape();
    for (int i=0; i<chainLength; i++){
      vertex(chain[i].x, chain[i].y); 
    }
    endShape();
 
 
  }
}
 
//----------------------------------------------------
// compute chain code to trace edge of a blob.
// this code only traces the first blob found, 
// where "first" is defined as "having a pixel with a lower index" (i.e. higher and to the left).
// for multi-blobs, separate code would be needed to label connected blobs first.
// (i.e. "connected component labelling").
 
//===============================================
class Point2d {
  int x,y;
}
 
 
//===============================================
int bri (int pixval){
  // compute the brightness of a pixel, as the average of the R,G,B values.
  int r = (pixval & 0x00FF0000) >> 16; 
  int g = (pixval & 0x0000FF00) >> 8; 
  int b = (pixval & 0x000000FF); 
  return (r+g+b)/3;
}
 
//===============================================
void findFirstPixel(){
  // find the first pixel of the first lit blob.
  boolean foundFirst = false;
  for (int y=0; y<height; y++){
    for (int x=0; x<width; x++){
      int val = pixels[y*width + x];
      if (!foundFirst && bri(val) > 0){
        firstPixel.x = x;
        firstPixel.y = y;
        foundFirst = true;
      }
    }
  }
}
 
//===============================================
boolean range (int n, int m){
  if (n < 0 || n >= width) return false;
  if (m < 0 || m >= height) return false;
  return true;
}
 
//===============================================
/*	Compute the chain code of the object beginning at pixel (i,j).
 	Return the code as NN integers in the array C.			*/
void chain8 (int i, int j){
  int val,n,m,q,r, ii, d, dii;
  int lastdir, jj;
 
  // Table given index offset for each of the 8 directions.	
  int di[] = {
    0,-1,-1,-1,0,1,1,1                  };
  int dj[] = {
    1,1,0,-1,-1,-1,0,1                  };
 
  for (ii=0; ii<MAX_CHAIN_LEN; ii++) {
    chain[ii].x = 0;
    chain[ii].y = 0;
  }
  val = pixels[j*width+i];	
  chainLength = 0;
  n = 0; /* Initialize for starting pixel */
  q = i;	
  r = j;  
  lastdir = 4;
 
  do {
    m = 0;
    dii = -1;	
    d = 100;
    for (ii=lastdir+1; ii<lastdir+8; ii++) { 	/* Look for next */
      jj = ii%8;
      if (range(di[jj]+q, dj[jj]+r)){
        if ( pixels[(dj[jj]+r)*width + (di[jj]+q)] == val) {
          dii = jj;	
          m = 1;
          break;
        } 
      }
    }
 
    if (m != 0) { /* Found the next pixel ... */
      if (n<MAX_CHAIN_LEN) {
        chain[n].x = q;
        chain[n].y = r;
        n++;
      }
      q += di[dii];	
      r += dj[dii];
      lastdir = (dii+5)%8;
    } 
    else {
      break; 	/* NO next pixel */
    }
    if (n>MAX_CHAIN_LEN) break;
  } 
  while ( (q!=i) || (r!=j) ); 	/* Stop when next to start pixel */
  chainLength = n;
}

Contour (Chain Code) Following

// compute chain code to trace edge of a blob.
// this code only traces the first blob found, 
// where "first" is defined as "having a pixel with a lower index" (i.e. higher and to the left).
// for multi-blobs, separate code would be needed to label connected blobs first.
// (i.e. "connected component labelling").
 
int MAX_CHAIN_LEN = 1000;
int chainLength = 0;
Point2d firstPixel;
Point2d chain[];
 
//===============================================
void setup(){
  size(400,400);
 
  firstPixel = new Point2d();
  chain = new Point2d[MAX_CHAIN_LEN];
  for (int i=0; i<MAX_CHAIN_LEN; i++){
    chain[i] = new Point2d();
  }  
}
 
//===============================================
class Point2d {
  int x,y;
}
 
 
//===============================================
void draw(){
 
  background(0);
  noStroke();
  fill(255);
  ellipse(mouseX,mouseY,140,150); 
  ellipse(230,200,100,70); 
  ellipse(280,190,60,120);
  strokeWeight(3);
  stroke(255,0,0); 
  noFill();
 
  loadPixels();
  findFirstPixel();
  chain8 (firstPixel.x, firstPixel.y);
 
  beginShape();
  for (int i=0; i<chainLength; i++){
    vertex(chain[i].x, chain[i].y); 
  }
  endShape();
 
}
 
//===============================================
int bri (int pixval){
  int r = (pixval & 0x00FF0000) >> 16; 
  int g = (pixval & 0x0000FF00) >> 8; 
  int b = (pixval & 0x000000FF); 
  return (r+g+b)/3;
}
 
//===============================================
void findFirstPixel(){
  boolean foundFirst = false;
  for (int y=0; y<height; y++){
    for (int x=0; x<width; x++){
      int val = pixels[y*width + x];
      if (!foundFirst && bri(val) > 0){
        firstPixel.x = x;
        firstPixel.y = y;
        foundFirst = true;
      }
    }
  }
}
 
//===============================================
boolean range (int n, int m){
  if (n < 0 || n >= width) return false;
  if (m < 0 || m >= height) return false;
  return true;
}
 
//===============================================
/*	Compute the chain code of the object beginning at pixel (i,j).
 	Return the code as NN integers in the array C.			*/
void chain8 (int i, int j){
  int val,n,m,q,r, ii, d, dii;
  int lastdir, jj;
 
  // Table given index offset for each of the 8 directions.	
  int di[] = {
    0,-1,-1,-1,0,1,1,1                  };
  int dj[] = {
    1,1,0,-1,-1,-1,0,1                  };
 
  for (ii=0; ii<MAX_CHAIN_LEN; ii++) {
    chain[ii].x = 0;
    chain[ii].y = 0;
  }
  val = pixels[j*width+i];	
  chainLength = 0;
  n = 0; /* Initialize for starting pixel */
  q = i;	
  r = j;  
  lastdir = 4;
 
  do {
    m = 0;
    dii = -1;	
    d = 100;
    for (ii=lastdir+1; ii<lastdir+8; ii++) { 	/* Look for next */
      jj = ii%8;
      if (range(di[jj]+q, dj[jj]+r)){
        if ( pixels[(dj[jj]+r)*width + (di[jj]+q)] == val) {
          dii = jj;	
          m = 1;
          break;
        } 
      }
    }
 
    if (m != 0) { /* Found the next pixel ... */
      if (n<MAX_CHAIN_LEN) {
        chain[n].x = q;
        chain[n].y = r;
        n++;
      }
      q += di[dii];	
      r += dj[dii];
      lastdir = (dii+5)%8;
    } 
    else {
      break; 	/* NO next pixel */
    }
    if (n>MAX_CHAIN_LEN) break;
  } 
  while ( (q!=i) || (r!=j) ); 	/* Stop when next to start pixel */
  chainLength = n;
}

Handy little programs

http://www.flong.com/blog/archives/85

Comparison of color extraction operators

 
color C = color (74,213,112,255); // R,G,B,A
 
long t0 = millis();
for (int i=0; i<786432; i++){
  int R = (C & 0x00FF0000) >> 16;
  int G = (C & 0x0000FF00) >>  8;
  int B = (C & 0x000000FF)      ;
}
println (millis() - t0);
 
long t1 = millis();
for (int i=0; i<786432; i++){
  float r = red(C);
  float g = green(C);
  float b = blue(C);
}
println (millis() - t1);

Simple interactive program

void setup(){
  size (400,300); 
}
 
void draw (){
  background (255,200,200);
  smooth ();
  strokeWeight (5);
  line (200,150, mouseX, mouseY);
}

Cat made of ellipses

PImage cat;
void setup(){
  size (400,300);
  cat = loadImage("Kitty.jpg");
}
 
void draw (){
  for (int i=0; i<500; i++){
    int rx = (int)random(cat.width);
    int ry = (int)random(cat.height);
    int index = ry*cat.width + rx;
 
    color C = cat.pixels[index];
    float Cr = red   (C);
    float Cg = green (C);
    float Cb = blue  (C);
    fill (Cr, Cg, Cb); 
    noStroke();
    ellipse (rx,ry, 15,15  );
  }
}

Cat made of interpolating line colors

PImage cat;
void setup(){
  size (400,400,P3D);
  cat = loadImage("Kitty.jpg");
  strokeWeight(3);
}
 
void draw (){
  for (int i=0; i<500; i++){
    int rx = (int)random(60, cat.width - 60);
    int ry = (int)random(60, cat.height - 60);
    int index = ry*cat.width + rx;
    int sx = rx + (int) random(-60,60);
    int sy = ry + (int) random(-60,60);
    int index2 = sy*cat.width + sx;
 
    color C = cat.pixels[index];
    float Cr = red   (C);
    float Cg = green (C);
    float Cb = blue  (C); 
    color D = cat.pixels[index2];
    float Dr = red   (D);
    float Dg = green (D);
    float Db = blue  (D);  
 
    beginShape();
    stroke(Cr,Cg,Cb);
    vertex(rx,ry);
    stroke(Dr,Dg,Db);
    vertex(sx,sy);
    endShape();
  }
}

Lines that Interpolate between Colors

size(300,400, P3D);
strokeWeight(10);
 
beginShape();
stroke(255,0,0);
vertex(30,30);
stroke(0,255,0);
vertex(120,180);
endShape();

Rotate an array

 
int array[];
array = new int[5];
array[0] = 666;
array[1] = 1;
array[2] = 2;
array[3] = 3;
array[4] = 4;
 
// ROTATE RIGHT
int temp = array[array.length-1];
for (int i=(array.length-1); i>0; i--){
  array[i] = array[i-1];
}
array[0] = temp;
 
// ROTATE LEFT
int temp = array[0];
for (int i=0; i< (array.length-1) ; i++){
  array[i] = array[i+1];
}
array[array.length-1] = temp;