How to Capture, Read, and Display a still image in a single program

edited November 2017 in Library Questions

Hello,

I'm currently writing a program that begins with taking a still image with the program, and then loads the still image in the same program for a sketch utilizing the still image as a background.

As a better overview, the concept is similar to the one in this program: https://www.openprocessing.org/sketch/117624 but instead of using a loaded image, the program will take a new image with the webcam each time it is run to use as the base.

Currently my method does so with a continuous live image as listed below, but I need it to work from a single still frame taken at the beginning of the program. Any help would be greatly appreciated!

import processing.video.*;

Capture myCam;

void setup() { myCam = new Capture(this); //Creating class, "this" uses live camera feed myCam.start(); fullScreen(); }

void draw() { //Draw when dragging if(myCam.available()){ myCam.read(); } }

Tagged:

Answers

  • Answer ✓

    Check the examples that come with the Video library. Under the Capture folder, there should be an example called backgroundSubtraction. Study the code and if you have any other question, write it down here. Also, please ensure you format your code in the forum. It is easy. Select the code block, then hit ctrl+o and don't forget to have add an empty line above and below your code block.

    Kf

  • Kf,

    Thanks for the reply. I've studied the example and I'm pretty sure I understand how it works, but I'm still struggling to adapt it to my project. The example seems to work based on creating a copied array at the press of a button and freezing the previous frame to the background, then tracking the live camera based on the color difference between what's now the background and the live feed.

    However, from what I understand this operates entirely by creating a new array that is layered over the frame saved as the background. With the code I've modified from the example, I'm not sure how to isolate just that background layer to draw on top of, based on the drawing method I have for sketching. I'll attach the code I'm working from right now (the drawing method still is gonna be modified, but that part can come later.

    I apologize for my lack of understanding, I'm a graduate architecture major taking a processing design class as a media elective, and I have no background in coding whatsoever. If you could please clear up how to utilize the techniques in the example I would appreciate it. Thanks

    import processing.video.*;
    
    Capture myCam;
    
    
    int
      WIDTH   = 1350, 
      HEIGHT  = 964, 
      MAX_AGE = 80, 
      LENGTH = 540, 
      FILL = #FFFFFF, 
      STROKE = -1, 
      ALFA = 75, 
      BACKGROUND = #000000;
    
    float
      SMOOTHNESS = .00023;
    
    PVector[] DIRECTIONS;
    int[][] INDEX;
    ArrayList<Particle> particles;
    
    
    void setup() {
      myCam = new Capture(this); //Creating class, "this" uses live camera feed
      myCam.start();
    
      fullScreen();
      fill(FILL, ALFA);
      noStroke();
      background(BACKGROUND);
    
      //LUT to store the indices associated with the vector field
      INDEX = new int[WIDTH][HEIGHT];
      for (int y = 0; y < HEIGHT; y++) for (int x = 0; x < WIDTH; x++) INDEX[x][y] = int(noise(x*SMOOTHNESS, y*SMOOTHNESS)*LENGTH); 
    
      //LUT to store the directions associated with the vector field
      DIRECTIONS = new PVector[LENGTH];
      for (int i = 0; i < LENGTH; i++) DIRECTIONS[i] = new PVector(cos(i*.5)*.05, sin(i*.5)*.05);  
    
      //Particles
      particles = new ArrayList<Particle>();
    
      //Base picture
    }
    
    void draw() {
      //Draw when dragging
      if (myCam.available()) {
        myCam.read();
      }
    
      if (mousePressed) particles.add(new Particle(mouseX, mouseY));       
    
      //Update the particles
      for (int i = 0; i < particles.size(); i++) 
      {
        Particle p = particles.get(i);
        if (p.isDead() == false) {
          p.update();
          p.draw();
        } else particles.remove(i);
      }
    } 
    
    //Clean canvas
    void keyPressed() {
      background(BACKGROUND);
    }
    
    class Particle
    {   
      //datafield
      PVector pos, vel;
      int x, y, s, rco, bco, gco, age;
    
      //constructor
      Particle(int _x_, int _y_)
      {
        x = _x_;
        y = _y_;
        pos = new PVector(x, y);
        vel = new PVector();
        age = MAX_AGE;
      }
    
      boolean isDead() { 
        return age==0;
      } 
    
      //method
      void draw() { 
        fill(red(rco), green(gco), blue(bco), s*17);
        ellipse(pos.x, pos.y, (4*s)/5, (4*s)/5);
    
      }  
    
      void update() 
      { 
        vel.add(DIRECTIONS[INDEX[(x + (WIDTH))% WIDTH][(y+HEIGHT)%HEIGHT]]);
        pos.add(vel);
        x = int(pos.x);
        y = int(pos.y);
        s = brightness(myCam.get(x, y)) >> 5;
        rco = color(red(myCam.get(x, y)));
        gco = color(green(myCam.get(x, y)));
        bco = color(blue(myCam.get(x, y)));
        age--;
      }   
    
      //Brightness Method
      int brightness(int c) { 
        int r = c >> 16 & 0xFF, g = c >> 8 & 0xFF, b = c & 0xFF; 
        return c = (c = r > g ? r : g) < b ? b : c;
      }
    }
    
  • Notice I modified the program to be able to observe the effect. I did:

    • Stop the camera after I got my single frame
    • Change the size of the ellipse so not to depend on s
    • Change the definition of s as >> 5 wasn't doing it for me
    • I changed the size of the cam resolution and the size of the sketch in setup
    • Re-defined your W and H variables
    • For the renderer, try using either P2D or Fx2D and see which one works better for you.

    Kf

    import processing.video.*;
    
    Capture myCam;
    
    
    int
      WIDTH   = 1350, 
      HEIGHT  = 964, 
      MAX_AGE = 80, 
      LENGTH = 540, 
      FILL = #FFFFFF, 
      STROKE = -1, 
      ALFA = 75, 
      BACKGROUND = #000000;
    
    float
      SMOOTHNESS = .00023;
    
    PVector[] DIRECTIONS;
    int[][] INDEX;
    ArrayList<Particle> particles;
    
    PImage singleImage=null;
    
    
    void setup() {
      myCam = new Capture(this, 640, 480, 30); //Creating class, "this" uses live camera feed
      myCam.start();
    
      size(640, 480, P2D);
      fill(FILL, ALFA);
      noStroke();
      background(BACKGROUND);
      imageMode(CENTER);
    
      WIDTH=width;
      HEIGHT=height;
    
      //LUT to store the indices associated with the vector field
      INDEX = new int[WIDTH][HEIGHT];
      for (int y = 0; y < HEIGHT; y++) 
        for (int x = 0; x < WIDTH; x++) 
          INDEX[x][y] = int(noise(x*SMOOTHNESS, y*SMOOTHNESS)*LENGTH); 
    
      //LUT to store the directions associated with the vector field
      DIRECTIONS = new PVector[LENGTH];
      for (int i = 0; i < LENGTH; i++) 
        DIRECTIONS[i] = new PVector(cos(i*.5)*.05, sin(i*.5)*.05);  
    
      //Particles
      particles = new ArrayList<Particle>();
    
      //Base picture
    }
    
    void draw() {
      //Draw when dragging
      if (myCam.available() && singleImage==null) {
        myCam.read();
        singleImage=myCam;
        image(singleImage, width/2, height/2);
        myCam.stop();
      }
    
      if (mousePressed) 
        particles.add(new Particle(mouseX, mouseY));       
    
      //Update the particles
      for (int i = particles.size()-1; i >=0; i--) 
      {
        Particle p = particles.get(i);
        if (p.isDead() == false) {
          p.update();
          p.draw();
        } else particles.remove(i);
      }
    } 
    
    //Clean canvas
    void keyPressed() {
      if (singleImage==null)
        background(BACKGROUND);
      else
        image(singleImage, width/2, height/2);
    }
    
    class Particle
    {   
      //datafield
      PVector pos, vel;
      int x, y, s, rco, bco, gco, age;
    
      //constructor
      Particle(int _x_, int _y_)
      {
        x = _x_;
        y = _y_;
        pos = new PVector(x, y);
        vel = new PVector();
        age = MAX_AGE;
      }
    
      boolean isDead() { 
        return age==0;
      } 
    
      //method
      void draw() { 
        fill((rco), (gco), (bco), s*17);
        ellipse(pos.x, pos.y, 5, 5);
      }  
    
      void update() 
      { 
        vel.add(DIRECTIONS[INDEX[(x + (WIDTH))% WIDTH][(y+HEIGHT)%HEIGHT]]);
        pos.add(vel);
        x = int(pos.x);
        y = int(pos.y);
        color cc=myCam.get(x, y);
        s = brightness(myCam.get(x, y)) >> 1;
        rco = cc>>16 & 0xff;
        gco = cc>>8 & 0xff;
        bco = cc & 0xff;
        age--;
      }   
    
      //Brightness Method
      int brightness(int c) { 
        int r = c >> 16 & 0xFF, g = c >> 8 & 0xFF, b = c & 0xFF; 
        return c = (c = r > g ? r : g) < b ? b : c;
      }
    }
    
Sign In or Register to comment.