How to change the opacity with movement

Hey guys! I am creating a prototype for an idea of an art history game. My idea is to have a piece of artwork behind a blank screen (in this case a white image) and as you move (movement coming from the laptop camera) will erase the white image to reveal the art piece. I am currently using frame differencing to accomplish this, but my code isn't working at all. The image is distorted somehow and what is happening is quite odd. If anyone has any ideas on how to improve or change the code to accomplish my idea, I would greatly appreciate it! Here is my code:

import processing.video.*; // Variable for capture device Capture video; // Previous Frame PImage prevFrame; // How different must a pixel be to be a "motion" pixel float threshold = 50;

PImage img; PImage img1;

void setup() { size(1200,700); //tint(200); img = loadImage( "van.jpg" ); size(1200,700);

video = new Capture(this, width, height, 30); prevFrame = createImage(video.width,video.height,RGB); video.start();

//size(1200, 700); // tint(255); // img1 = loadImage ( "white.png" );

}

void draw(){ // img.loadPixels(); // size(1200, 700); // tint(0); // img1 = loadImage ( "index.png" ); if (video.available()) { // Save previous frame for motion detection!! prevFrame.copy(video,0,0,video.width,video.height,0,0,video.width,video.height); // Before we read the new frame, we always save the previous frame for comparison! prevFrame.updatePixels(); video.read();

}

loadPixels(); video.loadPixels(); prevFrame.loadPixels(); //img1.loadPixels();

// Begin loop to walk through every pixel for (int x = 0; x < video.width; x ++ ) { for (int y = 0; y < video.height; y ++ ) {

  int loc = x + y*video.width;            // Step 1, what is the 1D pixel location
  //int loc = (video.width - x - 1) + y*video.width;
  color current =  prevFrame.pixels[loc]; //video.pixels[loc];      // Step 2, what is the current color
  color previous = video.pixels[loc]; //prevFrame.pixels[loc]; // Step 3, what is the previous color

  // Step 4, compare colors (previous vs. current)
  float r1 = red(previous); float g1 = green(previous); float b1 = blue(previous);
  float r2 = red(current); float g2 = green(current); float b2 = blue(current);
 float diff = dist(r1,g1,b1,r2,g2,b2);

  // Step 5, How different are the colors?
  // If the color at that pixel has changed, then there is motion at that pixel.
  if (diff > threshold) { 
    // If motion, display black  
//    img.pixels[prevFrame.pixels[loc]] = color( 0, 0, 0, 300 );
    pixels[(video.width - x - 1) + y*video.width] = color(0);
 // } else {
    // If not, display white
    pixels[(video.width - x - 1) + y*video.width] = img.pixels[loc];
  }
}

} updatePixels(); }

Answers

  • edited April 2015

    Indeed, the posting is a bit of a mess in terms of code. It's hard to know what's commented out and what isn't, which is particularly vexing when you have multiple versions of a line of code. So rather than try to reconstruct what you wrote, here's a program that I think accomplishes what you're after. I'm using the same color comparison you used (Euclidean distance in RGB space), which is generally a lousy way to compare colors, but might be a good choice in this application since it's fast and easy and probably close enough. I tried to generally stick to the basic approach it seemed like you were using.

    import processing.video.*; // Variable for capture device Capture video; 
    Capture Video;
    PImage SourceArt;  // the picture we're revealing
    PImage ArtSoFar;   // what we see now
    PImage ThisImage;  // what the camera sees now
    PImage PrevImage;  // what the camera saw one frame ago
    float ColorThreshold = 50;
    
    void setup() {
      size(1200, 700);
      SourceArt = loadImage( "van.jpg" ); 
      Video = new Capture(this, width, height, 30);
      Video.start();
      // the image we see starts out all white
      ArtSoFar = createImage(width, height, RGB);
      ArtSoFar.loadPixels();
      for (int y=0; y<height; y++) {
        for (int x=0; x<width; x++) {
          ArtSoFar.pixels[(y*width)+x] = color(255);
        }
      }
      ArtSoFar.updatePixels();
      // until the video arrives, the images don't exist yet
      ThisImage = null;
      PrevImage = null;
    }
    
    void draw() {  
      image(ArtSoFar, 0, 0);            // show the picture so far
      if (!Video.available()) return;   // if no video yet, return now
      Video.read();                     // read the frame into the Video buffer
      if (PrevImage == null) {          // is this the first time we have video?
        PrevImage = createImage(width, height, RGB);
        ThisImage = createImage(width, height, RGB);  
        // first time through, PrevImage and ThisImage will be the same, which is fine
        PrevImage.set(0, 0, Video);
      }
      // grab the current image into ThisImage for convenience
      ThisImage.set(0, 0, Video);
    
      // make sure we can read the pixels of all the images
      ThisImage.loadPixels();
      PrevImage.loadPixels();
      ArtSoFar.loadPixels();  
      SourceArt.loadPixels();
    
      for (int y=0; y<height; y++) {
        for (int x=0; x<width; x++) {
          int index = (y*width)+x;
          color thisColor = ThisImage.pixels[index];
          color prevColor = PrevImage.pixels[index];
          float diff = dist(red(thisColor), green(thisColor), blue(thisColor), 
          red(prevColor), green(prevColor), blue(prevColor));
          if (diff > ColorThreshold) {
            // these pixels are different in the video, so update the art from the source
            ArtSoFar.pixels[index] = SourceArt.pixels[index];
          }
        }
      }
    
      ArtSoFar.updatePixels();  // only the art has been changed
      // now copy the current image into the previous one to prepare for the next frame
      PrevImage.set(0, 0, ThisImage);
    }
    
Sign In or Register to comment.