Set specific pixels fully transparent in PGraphics

edited October 2 in Library Questions

Hi everyone, I am doing a demo about background subtraction and people extraction. I already picked the foreground pixels out of the whole pixels through comparing the different pixels between the static scene and later a people enter in this scene. I use createGraphics to store the foreground pixels and I would like to get a fully transparent background png. However, I only get a series of png files as normal camera feed frame, not the foreground extraction. I think the key section is here: if (diff > threshold) { pixels[loc] = fgColor; } else { pixels[loc] = color(0, 0); } I always get the error "NullPointerException" for the line" pg.pixels[loc] = color(0, 0); " so that I couldn't set the rest pixels as fully transparent.

Is there anyone have any idea about that? I have been trapped for too long but have no idea. Any help will be appreciated.

Here is the whole code if necessary:

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.noSmooth();
  pg.beginDraw();
  pg.background(0, 0);

  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);

//pg.loadPixels();


if (diff > threshold) {

  pg.pixels[loc] = fgColor;
} else {

  pg.pixels[loc] = color(0, 0); //color(gray, alpha)
  // pg.clear(); clears everything in a PGraphics object to make all of the pixels 100% transparen
}
    }
  }
  noFill();

    pg.updatePixels();
    pg.endDraw();
    image(pg, 0, 0);
    pg.save("image_" + millis() + ".png");
}

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

Answers

  • https://stackoverflow.com/questions/46415100/save-frames-of-background-subtraction-capture/46501004#46501004

    It sounds like you need to clear the PGraphics each frame. You could set it to a new PGraphics or you could use pg.clear() or pg.background(0,0,0,0) (set all pixels to transparent black).

  • Hi jeremydouglass, thanks for your response. I tried pg.clear() or pg.background(0,0,0,0) but I got cumulative drawing. I found that maybe the issue is to send PGraphics to each frame, not set the specific pixels transparent. But I have no idea how to put each PGraphics into each frame. Do you any further advice for that? Thanks a lot and looking forward to your reply.

  • I tried pg.clear() or pg.background(0,0,0,0) but I got cumulative drawing

    Please share your code. If you are actually clearing your PGraphics then it shouldn't still be there -- unless you are accumulating in a different PGraphics than you are clearing, or if you are copying from the main screen back into your PGraphics after clearing, etc.

  • edited October 3

    Hi jeremydouglass, thanks for your response. Here my code is. I think I didn't copy from the main screen. I still have no idea about that.

    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.noSmooth();
      pg.beginDraw();
      //pg.background(0, 0, 0, 0);
     pg.clear();
    
      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);
    
    //pg.loadPixels();
    
    
    if (diff > threshold) {
    
      pg.pixels[loc] = fgColor;
    } else {
    
      //pg.pixels[loc] = color(0, 0); //color(gray, alpha)
      // pg.clear(); clears everything in a PGraphics object to make all of the pixels 100% transparen
    }
        }
      }
      noFill();
    
        pg.updatePixels();
        pg.endDraw();
        image(pg, 0, 0);
        pg.save("image_" + millis() + ".png");
    }
    
    void mousePressed() {
      backgroundImage.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
      backgroundImage.updatePixels();
    }
    
Sign In or Register to comment.