For my first Computational Cameras assignment, I had to use facial tracking in some way. After coming up with a list of ideas, I decided to use facial tracking to give myself smoke coming out of my ears, as if I were steaming mad.
For the code, I utilized both Dan O’Sullivans OpenCV for good face tracking as well as Daniel Shiffman’s Smoke Particle System.
As it detects the user’s face, it pinpoints approximately where the ears are. Then, as long as there is a face in place, the particle systems continue to create smoke particles, following the user’s head around the screen. If the head disappears from the system, the smoke will continue to linger in the area.
Here are a few pictures (pardon my not so angry faces):
And here is my code:
Anger Smoke
import hypermedia.video.*;
import java.awt.Rectangle;
ParticleSystem xl, xr, hotness, hotn;
PVector loc, loca, locr, mouth;
float about, down;
boolean fire, made;
OpenCV cam;
void setup() {
size(320, 240);
smooth();
about = 5;
down = 1;
cam = new OpenCV(this);
cam.capture(width, height);
cam.cascade( OpenCV.CASCADE_FRONTALFACE_ALT);
loc = new PVector (-100, -100);
locr = new PVector (-100, -100);
mouth = new PVector (-100, -100);
xl = new ParticleSystem(100, loc, 3, about);
xr = new ParticleSystem(100, locr, 3, about);
loca = new PVector(0, 0);
}
void draw() {
background(255);
cam.read();
//cam.convert(GRAY);
image(cam.image(), 0, 0);
Rectangle[]faces = cam.detect();
if (faces.length == 0) {
loca = new PVector (-100, -100);
locr = new PVector (-100, -100);
mouth = new PVector(-100, -100);
}
for (int i = 0; i < faces.length; i++) {
noStroke();
//rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
loca = new PVector(faces[i].x, faces[i].y + faces[i].height/2);
locr = new PVector(faces[i].x + faces[i].width, faces[i].y + faces[i].height/2);
mouth = new PVector(faces[i].x + faces[i].width/2, faces[i].y + faces[i].height * 3/4);
//faceDetect(loc);
//fill(255, 0, 0, 50);
//ellipse(faces[i].x + faces[i].width/2, faces[i].y + faces[i].height/2, faces[i].width - 30, faces[i].height + 30);
}
xl.run(loca);
for ( int j = 0; j < 5; j++) {
xl.addParticle();
}
xr.run(locr);
for (int j = 0; j < 5; j++) {
xr.addParticle();
}
if (fire) {
if (made) {
hotness.run(mouth);
for ( int j = 0; j < 5; j++) {
hotness.addParticle();
}
hotn.run(mouth);
for( int k = 0; k < 5; k++){
hotn.addParticle();
}
}
else {
hotness = new ParticleSystem(1000, mouth, 2, down);
hotn = new ParticleSystem(1000, mouth, 1, down);
made = true;
}
}
else {
made = false;
}
fill(0);
// ellipse( loca.x, loca.y, 10, 10);
// ellipse( locr.x, locr.y, 10, 10);
}
//void faceDetect(PVector loca) {
// ps = new ParticleSystem(100, loca);
//}
void keyPressed() {
if (keyCode == ' ') {
fire = !fire;
if (fire) {
println("fire");
}
}
}
ParticleSystem
class ParticleSystem{
ArrayList particles;
PVector origin;
float siz = 10;
float colr, way;
ParticleSystem(int num, PVector loca, float col, float w){
colr = col;
particles = new ArrayList();
origin = loca.get();
way = w;
for (int i = 0; i < num; i++){ particles.add(new Particle(origin, colr, way)); } } void run(PVector loca){ origin = loca.get(); for (int i = particles.size() - 1; i >= 0; i--){
Particle p = (Particle) particles.get(i);
p.run();
if (p.dead()){
particles.remove(i);
}
}
}
void addParticle(){
particles.add(new Particle(origin, colr, way));
}
void addParticle(Particle p){
particles.add(p);
}
boolean dead(){
if (particles.isEmpty()) {
return true;
}
else {
return false;
}
}
}
and finally the particle
class Particle {
PVector loc, vel, accel, occel;
float siz, x, t;
float timer, mov;
Random gen = new Random();
Random gener = new Random();
float colr, y;
Particle (PVector l, float col, float direction) {
loc = l.get();
siz = 5;
t = 0;
timer = 80;
mov = direction;
y = (float) gen.nextGaussian() * 0.3f - 0.70f;
vel = new PVector (0, y);
accel = new PVector (0, 0);
colr = col;
}
void run() {
update();
display();
}
void update() {
t += .01;
float r = noise(t);
float x = map (r, 0, 1, -.3, .3);
float ye = map (r, 0, 1, -.1, .1);
accel = new PVector(x, 0);
occel = new PVector(ye, 0);
if (mov > 4) {
vel = new PVector (0, y);
}
else {
if (vel.y > 0){
vel = new PVector (0, timer - 75);
}
}
if ((colr == 1 || colr == 2)){
vel.add(occel);
}
else{
vel.add(accel);
}
loc.add(vel);
accel.mult(0);
timer = timer - .25;
}
void display() {
noStroke();
//fill(0, 0, 175, timer);
if (colr == 1) {
fill(255, 0, 0, timer - 60);
}
else if (colr ==2) {
fill(255, 102, 0, timer - 60);
}
else {
fill(175, timer);
}
ellipse(loc.x, loc.y, siz, siz);
}
boolean dead() {
if (timer <= 0.0) {
return true;
}
else {
return false;
}
}
}


Pingback: 10 ideas for Face Tracking « Comperas