/** * Read Signal Beacon State * by Robert Twomey. * * Read state of 3-state signal beacon. * With background subtraction. * * */ import processing.video.*; Capture video; // to define bounding box (smaller than the screen) int []upper, lower, left, right; // for background subtraction int numPixels; int[] backgroundPixels; int mode; static final int GREEN=0; static final int YELLOW=1; static final int RED=2; String [] modename = { "green", "yellow", "red" }; void setup() { size(640, 480); video = new Capture(this, width, height, 30); numPixels = video.width * video.height; // Create array to store the background image backgroundPixels = new int[numPixels]; // Make the pixels[] array available for direct manipulation loadPixels(); // initialize drawing params noStroke(); smooth(); // initialize bounding box upper= new int [] { 0, 0, 0 }; left= new int [] { 0, 0, 0 }; lower= new int [] { height, height, height }; right= new int [] { width, width, width }; mode=GREEN; } void doBgSubtraction() { // Difference between the current frame and the stored background int presenceSum = 0; for (int i = 0; i < numPixels; i++) { // For each pixel in the video frame... // Fetch the current color in that location, and also the color // of the background in that spot color currColor = video.pixels[i]; color bkgdColor = backgroundPixels[i]; // Extract the red, green, and blue components of the current pixel’s color int currR = (currColor >> 16) & 0xFF; int currG = (currColor >> 8) & 0xFF; int currB = currColor & 0xFF; // Extract the red, green, and blue components of the background pixel’s color int bkgdR = (bkgdColor >> 16) & 0xFF; int bkgdG = (bkgdColor >> 8) & 0xFF; int bkgdB = bkgdColor & 0xFF; // Compute the difference of the red, green, and blue values int diffR = abs(currR - bkgdR); int diffG = abs(currG - bkgdG); int diffB = abs(currB - bkgdB); // Add these differences to the running tally presenceSum += diffR + diffG + diffB; // Render the difference image to the screen //pixels[i] = color(diffR, diffG, diffB); // The following line does the same thing much faster, but is more technical pixels[i] = 0xFF000000 | (diffR << 16) | (diffG << 8) | diffB; } updatePixels(); // Notify that the pixels[] array has changed } void draw() { if (video.available()) { video.read(); video.loadPixels(); // Make the pixels of video available image(video, 0, 0, width, height); // Draw the webcam video onto the screen int reddestX = 0; // X-coordinate of the brightest video pixel int reddestY = 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(); doBgSubtraction(); video.updatePixels(); // Draw a large, yellow circle at the brightest pixel fill(255, 0, 0, 128); if(brightestValue > 192) ellipse(reddestX, reddestY, 20, 20); } drawBoundingBoxes(); switch(mode) { case RED: fill(255, 0, 0); break; case YELLOW: fill(255, 255, 0); break; case GREEN: fill(0, 255, 0); break; } rect(width-20, 10, 10, 10); drawIntensityBar(GREEN, 10, 10, 20, 100); drawIntensityBar(YELLOW, 40, 10, 20, 100); drawIntensityBar(RED, 70, 10, 20, 100); } void drawBoundingBoxes() { noFill(); stroke(255, 0, 0); rect(left[RED], upper[RED], right[RED]-left[RED], lower[RED]-upper[RED]); stroke(255, 255, 0); rect(left[YELLOW], upper[YELLOW], right[YELLOW]-left[YELLOW], lower[YELLOW]-upper[YELLOW]); stroke(0, 255, 0); rect(left[GREEN], upper[GREEN], right[GREEN]-left[GREEN], lower[GREEN]-upper[GREEN]); noStroke(); } void drawIntensityBar(int whichbox, int x, int y, int w, int h) { switch(whichbox) { case RED: fill(255, 0, 0); break; case YELLOW: fill(255, 255, 0); break; case GREEN: fill(0, 255, 0); break; } rect(x, y, w, map(sumIntensity(whichbox), 0, (lower[whichbox]-upper[whichbox])*(right[whichbox]-left[whichbox])*255, 0, h)); } int sumIntensity(int whichbox) { int index; int sum=0; for (int y = upper[whichbox]; y < lower[whichbox]; y++) { for (int x = left[whichbox]; x < right[whichbox]; x++) { index = x + y * video.width; // Get the color stored in the pixel int pixelValue = pixels[index]; // Determine the brightness of the pixel int pixelBrightness = round(brightness(pixelValue)); // If that value is brighter than any previous, then store the // brightness of that pixel, as well as its (x,y) location sum+=pixelBrightness; } } return sum; } // When a key is pressed, capture the background image into the backgroundPixels // buffer, by copying each of the current frame’s pixels into it. void keyPressed() { if(key==' ') { video.loadPixels(); arraycopy(video.pixels, backgroundPixels); } if(key=='y') mode=YELLOW; if(key=='r') mode=RED; if(key=='g') mode=GREEN; } // mouse stuff to specify smaller bounding box than full-frame image. void mousePressed() { upper[mode]=mouseY; left[mode]=mouseX; } void mouseDragged() { lower[mode]=mouseY; right[mode]=mouseX; } void mouseReleased() { lower[mode]=mouseY; right[mode]=mouseX; if(upper[mode]>lower[mode]) { int temp=upper[mode]; upper[mode]=lower[mode]; lower[mode]=temp; } if(right[mode]