Not a lot of subtracting going on in here! :)
Well, progress so far, but the logic behind what I wanted to do doesn't really appear to be a "best practice" way of doing it.
Using JMyron, I was able to get the average pixel color of the background and then compare it to that of the current scene, but this way of doing things seem to rely heavily on stable conditions for the background. When, for instance, it gets sunnier in a room the background no longer matches. This can be solved by increasing the tolerance, but that also seems to be a strange way to go about it. All together, using the average colour of a pixel to determine change seems to be flawed in cases where there is no control due to the fact that, say, the person passing by could be wearing the same colour as the background and sneak by undetected.
Does anyone have any other ways one might accomplish this task of background subtraction?
My current code is below so you can see.
Pressing < / > increases and decreases the tolerance and hitting the spacebar takes a new snapshot of the background.
Thanks in advance!
- import JMyron.*;
- int NUM_SQUARES = 50;
- color [] gridArray;
- color [] currFrame;
- int tolerance = 80;
- boolean revealing;
- JMyron theMov;
- int sampleWidth, sampleHeight;
- int numSamplePixels;
- void setup() {
- size(320, 240);
- frameRate(5);
- theMov = new JMyron();
- theMov.start(width, height);
- theMov.findGlobs(0);
- currFrame = new color[10100];
- gridArray = new color[10100];
- sampleWidth = width/NUM_SQUARES;
- sampleHeight = height/NUM_SQUARES;
- numSamplePixels = sampleWidth*sampleHeight;
- //capture initial background
- refreshBackground(theMov);
- }
- void draw() {
- theMov.update();
- // go through all the cells
- for (int y=0; y <= NUM_SQUARES; y++) {
- for (int x=0; x < NUM_SQUARES; x++) {
-
- int indexOfGrid = (x+y*NUM_SQUARES);
- //println(indexOfGrid);
- currFrame[indexOfGrid] = theMov.average(x*sampleWidth,y*sampleHeight,(x*sampleWidth)+sampleWidth,(y*sampleHeight)+sampleWidth);
-
- if(comparePixels(indexOfGrid)){
- fill(255,255,255);
- rect(x*sampleWidth, y*sampleHeight, sampleWidth, sampleHeight);
- }else{
- fill(0,0,0);
- rect(x*sampleWidth, y*sampleHeight, sampleWidth, sampleHeight);
- }
- }
- }
- }
- boolean comparePixels(int index) {
- if ((Math.abs(red(currFrame[index]))-(red(gridArray[index]))) < tolerance ||
- (Math.abs(green(currFrame[index]))-(green(gridArray[index]))) < tolerance ||
- (Math.abs(blue(currFrame[index]))-(blue(gridArray[index]))) < tolerance){
- return !revealing;
- }else{
- return revealing;
- }
- }
- void refreshBackground(JMyron movObj){
- movObj.update();
- for (int y=0; y < NUM_SQUARES; y++) {
- for (int x=0; x < NUM_SQUARES; x++) {
- int indexOfGrid = (x+y*NUM_SQUARES);
- gridArray[indexOfGrid] = movObj.average(x*sampleWidth,y*sampleHeight,(x*sampleWidth)+sampleWidth,(y*sampleHeight)+sampleWidth);
- }
- }
- }
- void keyReleased() {
- if (key == '.' || key == '>') {
- // increase tolerance
- tolerance += 2;
- } else if (key == ',' || key == '<') {
- // decrease tolerance
- tolerance -= 2;
- // take a new snapshot
- } else if (key == ' ') {
- refreshBackground(theMov);
- }
- }
- public void stop() {
- theMov.stop();
- super.stop();
- }