163 lines
4.1 KiB
Plaintext
163 lines
4.1 KiB
Plaintext
/**
|
|
* WhichFace
|
|
* Daniel Shiffman
|
|
* http://shiffman.net/2011/04/26/opencv-matching-faces-over-time/
|
|
*
|
|
* Modified by Jordi Tost (@jorditost) to work with the OpenCV library by Greg Borenstein:
|
|
* https://github.com/atduskgreg/opencv-processing
|
|
*
|
|
* @url: https://github.com/jorditost/BlobPersistence/
|
|
*
|
|
* University of Applied Sciences Potsdam, 2014
|
|
*/
|
|
|
|
import gab.opencv.*;
|
|
import processing.video.*;
|
|
import java.awt.*;
|
|
|
|
Capture video;
|
|
OpenCV opencv;
|
|
|
|
// List of my Face objects (persistent)
|
|
ArrayList<Face> faceList;
|
|
|
|
// List of detected faces (every frame)
|
|
Rectangle[] faces;
|
|
|
|
// Number of faces detected over all time. Used to set IDs.
|
|
int faceCount = 0;
|
|
|
|
// Scaling down the video
|
|
int scl = 2;
|
|
|
|
void setup() {
|
|
size(640, 480);
|
|
video = new Capture(this, width/scl, height/scl);
|
|
opencv = new OpenCV(this, width/scl, height/scl);
|
|
opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
|
|
|
|
faceList = new ArrayList<Face>();
|
|
|
|
video.start();
|
|
}
|
|
|
|
void draw() {
|
|
scale(scl);
|
|
opencv.loadImage(video);
|
|
|
|
image(video, 0, 0 );
|
|
|
|
detectFaces();
|
|
|
|
// Draw all the faces
|
|
for (int i = 0; i < faces.length; i++) {
|
|
noFill();
|
|
strokeWeight(5);
|
|
stroke(255,0,0);
|
|
//rect(faces[i].x*scl,faces[i].y*scl,faces[i].width*scl,faces[i].height*scl);
|
|
rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
|
|
}
|
|
|
|
for (Face f : faceList) {
|
|
strokeWeight(2);
|
|
f.display();
|
|
}
|
|
}
|
|
|
|
void detectFaces() {
|
|
|
|
// Faces detected in this frame
|
|
faces = opencv.detect();
|
|
|
|
// Check if the detected faces already exist are new or some has disappeared.
|
|
|
|
// SCENARIO 1
|
|
// faceList is empty
|
|
if (faceList.isEmpty()) {
|
|
// Just make a Face object for every face Rectangle
|
|
for (int i = 0; i < faces.length; i++) {
|
|
println("+++ New face detected with ID: " + faceCount);
|
|
faceList.add(new Face(faceCount, faces[i].x,faces[i].y,faces[i].width,faces[i].height));
|
|
faceCount++;
|
|
}
|
|
|
|
// SCENARIO 2
|
|
// We have fewer Face objects than face Rectangles found from OPENCV
|
|
} else if (faceList.size() <= faces.length) {
|
|
boolean[] used = new boolean[faces.length];
|
|
// Match existing Face objects with a Rectangle
|
|
for (Face f : faceList) {
|
|
// Find faces[index] that is closest to face f
|
|
// set used[index] to true so that it can't be used twice
|
|
float record = 50000;
|
|
int index = -1;
|
|
for (int i = 0; i < faces.length; i++) {
|
|
float d = dist(faces[i].x,faces[i].y,f.r.x,f.r.y);
|
|
if (d < record && !used[i]) {
|
|
record = d;
|
|
index = i;
|
|
}
|
|
}
|
|
// Update Face object location
|
|
used[index] = true;
|
|
f.update(faces[index]);
|
|
}
|
|
// Add any unused faces
|
|
for (int i = 0; i < faces.length; i++) {
|
|
if (!used[i]) {
|
|
println("+++ New face detected with ID: " + faceCount);
|
|
faceList.add(new Face(faceCount, faces[i].x,faces[i].y,faces[i].width,faces[i].height));
|
|
faceCount++;
|
|
}
|
|
}
|
|
|
|
// SCENARIO 3
|
|
// We have more Face objects than face Rectangles found
|
|
} else {
|
|
// All Face objects start out as available
|
|
for (Face f : faceList) {
|
|
f.available = true;
|
|
}
|
|
// Match Rectangle with a Face object
|
|
for (int i = 0; i < faces.length; i++) {
|
|
// Find face object closest to faces[i] Rectangle
|
|
// set available to false
|
|
float record = 50000;
|
|
int index = -1;
|
|
for (int j = 0; j < faceList.size(); j++) {
|
|
Face f = faceList.get(j);
|
|
float d = dist(faces[i].x,faces[i].y,f.r.x,f.r.y);
|
|
if (d < record && f.available) {
|
|
record = d;
|
|
index = j;
|
|
}
|
|
}
|
|
// Update Face object location
|
|
Face f = faceList.get(index);
|
|
f.available = false;
|
|
f.update(faces[i]);
|
|
}
|
|
// Start to kill any left over Face objects
|
|
for (Face f : faceList) {
|
|
if (f.available) {
|
|
f.countDown();
|
|
if (f.dead()) {
|
|
f.delete = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Delete any that should be deleted
|
|
for (int i = faceList.size()-1; i >= 0; i--) {
|
|
Face f = faceList.get(i);
|
|
if (f.delete) {
|
|
faceList.remove(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void captureEvent(Capture c) {
|
|
c.read();
|
|
}
|