Quantcast
Channel: Processing Forum
Viewing all articles
Browse latest Browse all 1768

Interactive Webcam code - Help needed!

$
0
0
This is my first semester learning processing, and clearly, I'm no expert. I have a final presentation in which I'm supposed to
create an interactive display at an Art Exhibit. I'm attempting to use the flob library to detect movement on a webcam and use that movement to interact with the balls bouncing around on the screen. The collision part of the code is working, but I'm not content with just that. Not only is the image pixelated but it's also pretty bland.

So I set up an array function to create a purple trace of the movements detected by the webcam, and I'm trying to overlay this capture on top of the pixelated one.

Hoping for some answers, because I cannot for the life of me get this to cooperate.

The flob Library can be downloaded here.

My code currently is as follows:

  1. import processing.opengl.*;
    import processing.video.*;
    import s373.flob.*;

    Capture video;
    Flob flob;
    PImage videoinput;

    int videoResolution = 128;
    int fps = 60;
    int max_balls = 20;

    Ball balls[] = new Ball[max_balls];

    boolean om = true, omset = false;
    float velmult = 10000.0f;

    final int videoWidth  = 320;
    final int videoHeight = 240;

    // Number of Quadrants in Width and Height
    final int videoColumns   = videoWidth/2;
    final int videoRows   = videoHeight/2;

    float[] activity = new float[videoColumns * videoRows];
    float[] buffer1 = new float[videoWidth * videoHeight];
    float[] buffer2 = new float[buffer1.length];
    float[] buffer3 = new float[buffer1.length];

    void setup() {

      size(640, 480, OPENGL);
      frameRate(fps);
      smooth();

      video = new Capture(this, videoWidth, videoHeight);
      video.start();

      // create one image with the dimensions you want flob to run at
      videoinput = createImage(videoResolution, videoResolution, RGB);

      // construct flob
      flob = new Flob(this, videoResolution, videoResolution, width, height);
      flob.setThresh(10);
      //Sensitivity - Default 45
      flob.setFade(80);
      flob.setMinNumPixels(10);


      balls = new Ball[max_balls];
      for (int i=0; i < balls.length; i++) {
        balls[i] = new Ball();
      }
    }

    void draw() {
      background(0);

      if (video.available() == true) {  
        if (!omset) {
          if (om)
            flob.setOm(flob.CONTINUOUS_DIFFERENCE);
          else
            flob.setOm(flob.STATIC_DIFFERENCE);
          omset=true;
        }
        video.read();

        int index;
        int pixelsPerCol = videoWidth / videoColumns;
        int pixelsPerRow = videoHeight / videoRows;

         image (video, 0, 0);

        // 'activity' array set to zero
        for (int i=0; i < activity.length; i++) {
          activity[i] = 0;
        }

        // For each pixel in the video frame
        for (int i=0; i < video.pixels.length; i++) {
          // x and y Position calculate the quadrant
          int x = (int) ((i % video.width) / pixelsPerCol);
          int y = (int) ((i / video.width) / pixelsPerRow);
          // Quadrant membership of the pixel to find out.
          // Later important for the 'activity' array.
          index = y * videoColumns + x;
          // Color at position 'i' in the camera image
          color col = video.pixels[i];
          // The sum of all three color channels
          float sum = red (col) + green (col) + blue (col);
          // Change the pixel color value calculated based on all images
          float deltaPixel = (buffer1[i] + buffer2[i] + buffer3[i]) / 3 - sum;
          if (deltaPixel < 0) {
            deltaPixel *= -1;
          }
          // Add the change to the total value of the quadrant
          activity[index] += deltaPixel;
          // Move the 'image memory' a step backwards.
          buffer3[i] = buffer2[i];
          buffer2[i] = buffer1[i];
          buffer1[i] = sum;
        }     

        for (int i=0; i < activity.length; i++) {

          // Calculate average color value change by dividing the sum by the number of pixels
          activity[i] /= pixelsPerCol * pixelsPerRow;
          if (activity[i]>=255)
            //     println(i);

            // Drawing of quadrants on the display
            stroke (0, 0);
          // Changes the color of the movement displayed
          fill (150, 50, 250, activity[i]);
          rect ((i % videoColumns) * pixelsPerCol, (i / videoColumns) * pixelsPerRow, pixelsPerCol, pixelsPerRow);
        }

        //downscale video image to videoinput pimage
       // tint(255, 0); ---- End goal is to have this be hidden
        videoinput.copy(video, 0, 0, 320, 240, 0, 0, videoResolution, videoResolution);
        // Here is defined the method of calculation: calc, calcsimple, or tracksimple
        // Tracksimple is more accurate, but is much more data intensive than calcsimple
        //    flob.tracksimple(  flob.binarize(video) );
        flob.calcsimple(  flob.binarize(videoinput) );
      }

      //Displays the actual webcam stream
      image(flob.getSrcImage(), 0, 0, width, height);

      // collision
      float collisionData[] = new float[5];
      for (int i = 0; i<balls.length; i++) {
        float x = balls[i].x / (float) width;
        float y = balls[i].y / (float) height;
        collisionData = flob.imageblobs.postcollidetrackedblobs(x, y, balls[i].radius/(float)width);
        if (collisionData[0] > 0) {
          balls[i].collision = true;
          balls[i].xSpeed += collisionData[1] * width * 0.015;
          balls[i].ySpeed += collisionData[2] * height * 0.015;
          //balls[i].radius = 0;
        }
        else {
          balls[i].collision = false;
        }
        balls[i].run();
      }
    }


    void keyPressed() {
      if (key=='o') {
        om^=true;
        omset=false;
      }
    }

    class Ball {
      float x, y;
      float xSpeed, ySpeed;
      float radius = random(5, 25);
      boolean collision = false;

      Ball() {
        init();
      }

      void init() {
        xSpeed = random(-1.1, 1.1);
        ySpeed = random(1.5);
        x = random(width);
        y = random(-100, -50);
      }

      void update() {
        x += xSpeed;
        y += ySpeed;

        if (abs(xSpeed) > 3)
          xSpeed *= 0.9;
        if (abs(ySpeed) > 3)
          ySpeed *= 0.9;

        if (x < radius) {
          x = radius;
          xSpeed = -xSpeed;
        }
        if (x > width - radius) {
          x = width - radius;
          xSpeed = -xSpeed;
        }
        if (y < 0 + radius) {
          y = 0 + radius;
          ySpeed = -ySpeed;
        }
        if (y>height-radius) {
          y=height-radius;
          ySpeed = -ySpeed;
        }
      }

      void draw() {
        if (!collision)
        {
          fill(0, 255, 0);
        }
        else
          fill(255, 0, 0);
        ellipse(x, y, radius*2, radius*2);
      }

    void run() {
      update();
      draw();
    }
    }

Thank you!


Viewing all articles
Browse latest Browse all 1768

Trending Articles