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:
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:
- 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();
}
}