I am working in an Interactive project and I am trying to define the correct area inside the body silhouette.
The sketch is using OpenCV, Delaunay triangulation and the goal is to add Box2D for the interaction.
My question is how to filter those triangles that are not included in the human silhouette? If you run the code, you will see that the triangulation, of course, is taking into account all the points detected by OpenCV, that means it will define triangles outside the human shape; however, the human shape is perfectly defined by contour.getPolygonApproximation().getPoints() and fill(255, 150, 0); beginShape(); is drawing a very nice shadow. Perhaps, getting the colour of the centre pixel of the triangle can tell me if that triangle is inside or outside the human body. Need some help here.
triangulation library is here: http://n.clavaud.free.fr/processing/triangulate/triangulate-20100628.zip
The triangles that are ok are those inside the orange area.
The code:
/**
* Background Subtraction
* by Golan Levin.
* Example by David Dalmazzo
* Detect the presence of people and objects in the frame using a simple
* background-subtraction technique. To initialize the background, press spacebar.
*/
import org.processing.wiki.triangulate.*;
import processing.video.*;
import gab.opencv.*;
int numPixels;
PImage backgroundPixels;
PImage frontPixels;
ArrayList<Contour> contours;
ArrayList<Contour> polygons;
ArrayList triangles = new ArrayList();
ArrayList points = new ArrayList();
int threshold = -74;
boolean isBGReady = false;
boolean drawCoutour = false;
OpenCV opencv;
Capture video;
void setup() {
size(640, 480, P2D);
video = new Capture(this, 640, 480);
opencv = new OpenCV(this, 640, 480);
opencv.threshold(100);
// Start capturing the images from the camera
video.start();
numPixels = video.width * video.height;
// Create array to store the background image
if(isBGReady)backgroundPixels = loadImage("backgroundPixels.jpg");
else backgroundPixels = createImage(width, height, RGB);
frontPixels = createImage(width, height, RGB);
// Make the pixels[] array available for direct manipulation
loadPixels();
}
void draw() {
background(0);
if (video.available()) {
video.read(); // Read a new video frame
video.loadPixels(); // Make the pixels of video available
frontPixels = video.copy();
backgroundPixels.loadPixels();
frontPixels.loadPixels();
for (int i = 0; i < numPixels; i++) { // For each pixel in the video frame...
// Fetch the current color in that location, and also the color
// of the background in that spot
color currColor = frontPixels.pixels[i];
color bkgdColor = backgroundPixels.pixels[i];
// Extract the red, green, and blue components of the current pixel's color
int currR = (currColor >> 16) & 0xFF;
int currG = (currColor >> 8) & 0xFF;
int currB = currColor & 0xFF;
// Extract the red, green, and blue components of the background pixel's color
int bkgdR = (bkgdColor >> 16) & 0xFF;
int bkgdG = (bkgdColor >> 8) & 0xFF;
int bkgdB = bkgdColor & 0xFF;
// Compute the difference of the red, green, and blue values
int diffR = abs(currR - bkgdR);
int diffG = abs(currG - bkgdG);
int diffB = abs(currB - bkgdB);
// Add these differences to the running tally
// Render the difference image to the screen
//frontPixels.pixels[i] = color(diffR, diffG, diffB);
// The following line does the same thing much faster, but is more technical
frontPixels.pixels[i] = 0xFF000000 | (diffR << 16) | (diffG << 8) | diffB;
}
frontPixels.updatePixels(); // Notify that the pixels[] array has changed
//println(presenceSum); // Print out the total amount of movement
}
if (!isBGReady) {
image(frontPixels, 0, 0, width, height);
} else {
opencv.loadImage(frontPixels);
opencv.brightness(threshold);
//find contours in real-time
contours = opencv.findContours(true, true);
for (Contour contour : contours) {
contour.setPolygonApproximationFactor(5.0);
if (drawCoutour) {
noFill();
stroke(0, 150, 250);
contour.draw();
} else {
noStroke ();
fill(255, 150, 0);
beginShape();
for (PVector point : contour.getPolygonApproximation().getPoints()) {
if (point.x > 1 && point.x < frontPixels.width-2 && point.y > 1 && point.y < frontPixels.height-2) {
vertex(point.x, point.y);
points.add(new PVector(point.x, point.y));
}
}
endShape();
}
}
}
if (points.size() > 3) {
triangles = Triangulate.triangulate(points);
stroke(255, 50);
fill(0, 150, 255, 50);
beginShape();
for (int i = 0; i < triangles.size(); i++) {
Triangle t = (Triangle)triangles.get(i);
vertex(t.p1.x, t.p1.y);
vertex(t.p2.x, t.p2.y);
vertex(t.p3.x, t.p3.y);
}
endShape();
}
points.clear();
fill(255);
text(frameRate, 5, 12);
}
// When a spacebar is pressed, capture the background image into the backgroundPixels
void keyPressed() {
if (key == ' ') {
video.loadPixels();
backgroundPixels = video.copy();
backgroundPixels.save("backgroundPixels.jpg");
isBGReady = true;
}
if (key == 'c') {
drawCoutour =! drawCoutour;
}
}
void mouseDragged() {
threshold = (int)map(mouseX, 0, width, -1, -255);
println(threshold );
}