Save frames of background subtraction capture

edited September 2017 in Library Questions

Hi everyone, I am doing a background subtraction capture demo recently but I met with difficulties. I have already get the pixel of silhouette extraction and I intend to draw it into a buffer through createGraphics(). I set the new background is 100% transparent so that I could only get the foreground extraction. Then I use saveFrame() function in order to get png file of each frame. However, it doesn't work as I expected.I intend to get a series of png of the silhouette extraction with 100% transparent background but now I only get the general png of frames from the camera feed. Is there anyone could help me to see what's the problem with this code? Thanks a lot in advance. Any help will be appreciated.

import processing.video.*;

Capture video;

PGraphics pg;

PImage backgroundImage;
float threshold = 30;

void setup() {
  size(320, 240);
  video = new Capture(this, width, height);
  video.start();

  backgroundImage = createImage(video.width, video.height, RGB); 
  pg = createGraphics(320, 240);
}

void captureEvent(Capture video) {
  video.read();
}

void draw() {
  pg.beginDraw();

  loadPixels();
  video.loadPixels();
  backgroundImage.loadPixels();

  image(video, 0, 0);
  for (int x = 0; x < video.width; x++) {
    for (int y = 0; y < video.height; y++) {
      int loc = x + y * video.width;



color fgColor = video.pixels[loc];
color bgColor = backgroundImage.pixels[loc];

float r1 = red(fgColor); float g1 = green(fgColor); float b1 = blue(fgColor);
float r2 = red(bgColor); float g2 = green(bgColor); float b2 = blue(bgColor);
float diff = dist(r1, g1, b1, r2, g2, b2);


if (diff > threshold) {
  pixels[loc] = fgColor;
} else {
  pixels[loc] = color(0, 0);
}
    }}
    pg.updatePixels();
    pg.endDraw();


    saveFrame("line-######.png");
}


void mousePressed() {
  backgroundImage.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
  backgroundImage.updatePixels();
}

Answers

  • You should consider checking the reference: https://processing.org/reference/PGraphics.html

    In your case, line 30 could be pg.image(video,0,0); for instance. Then you need to work with your PGraphics directly in your code. This last coment is to give you a better idea how you can work with PGraphics. PGraphics allows you to create a second buffer where you can manipulate pixels. In your case, what you want to do is to clear the PGraphics at the beginning of draw, to maintain full transparency, and then modify the PGraphics (line 45) like this:

     if (diff > threshold) {
      pg.pixels[loc] = fgColor;
    }
    

    No need of the else block if you are clearing the PGraphics.

    Kf

  • Alternately, you could use pg.save().

    Either draw your results to the main sketch screen and then use saveFrame(), or leave the results in pg and use pg.save()

  • @kfrajer Thanks for your advice. I tried this but I got the error'NullPointerException' in this line: pg.image(video,0,0);Do you have any further advice about that? Looking forward to your reply.

  • @kfrajer Please ignore my last reply and I have solved it. I made a change from line 45 to 49:

    if (diff > threshold) {
      pg.pixels[loc] = fgColor;
    } else {
      pg.pixels[loc] = color(0, 0);
    }
    

    As I intend to get a full transparent png, I apply pg.pixels[loc] = color(0, 0);However, I got the error'NullPointerException' in this line. Do you have any idea about that? Thanks a lot.

  • edited September 2017

    Maybe I should post the code I have so far as I am not sure which part is wrong.

    import processing.video.*;
    
    Capture video;
    
    PGraphics pg;
    
    PImage backgroundImage;
    float threshold = 30;
    
    void setup() {
      size(320, 240);
      video = new Capture(this, width, height);
      video.start();
    
      backgroundImage = createImage(video.width, video.height, RGB); 
      pg = createGraphics(320, 240);
    }
    
    void captureEvent(Capture video) {
      video.read();
    }
    
    void draw() {
    
      loadPixels();
      video.loadPixels();
      backgroundImage.loadPixels();
    
      pg.beginDraw();
    
      pg.image(video,0,0);
      for (int x = 0; x < video.width; x++) {
        for (int y = 0; y < video.height; y++) {
          int loc = x + y * video.width;
    
    
    
    color fgColor = video.pixels[loc];
    color bgColor = backgroundImage.pixels[loc];
    
    float r1 = red(fgColor); float g1 = green(fgColor); float b1 = blue(fgColor);
    float r2 = red(bgColor); float g2 = green(bgColor); float b2 = blue(bgColor);
    float diff = dist(r1, g1, b1, r2, g2, b2);
    
    
    if (diff > threshold) {
      pg.pixels[loc] = fgColor;
    } else {
      pg.pixels[loc] = color(0, 0);
    }
    
    }
    }  
        pg.endDraw();
        pg.save("line-######.png");
    }
    
    void mousePressed() {
      backgroundImage.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
      backgroundImage.updatePixels();
    }
    
  • @jeremydouglass Thanks for your answer and I have tried but it doesn't work. I think maybe the fundamental error is the PGraphics.

  •       int loc = x + y * video.width;
    

    Y should be your outer loop -- but don't bother with this. Instead just loop through the length of pixels[] (minus 1).

Sign In or Register to comment.