Faces is work that achieves no clear goal, does not infer a
motive, nor does it follow conventional rules regarding art. It may be best to
consider it close to a Dadaist or anti-art work because if anything it’s
mocking art. The project started as several ideas and has slowly merged into
one clearly identifiable work.
Concept number one was an idea that with a phone you could
write on a virtual wall at any time. Drawn from a project that allowed users to
virtually draw on buildings with laser pointers it was a natural urge to try
and condense the huge space the original project worked in to a small show
room. For this we would use a camera watching a crowd in front of a projected
mirror or essentially an image on the crowd just projected in front of the
crowd. The crowd would watch the mirror and see themselves with but with a slight
twist. If someone pulled out their phone and opened an app that turned the
screen a green screen green you could then write on the mirror with your phone
by holding it up to the camera. The technical details are simple enough. A
camera watching the crowd would be looking for a certain color AKA green screen
green. If it were to see the color it changes the pixels where the green is and
output to a solid color. The projector showing the mirror then displays this altered
image with a drawing on it. The total effect makes the user fell like he/she is
drawing on the mirror with a phone. The idea was great for several reasons.
First it was user interactive which in my opinion is always very important.
Second the user controls the outcome of the work. Once the program is set, it is
left to the masses for them to decide its fate. The implementation of this was
more complex than we could attempt in a 4 week assignment so we moved on to our
next idea.
This idea was drawn from two different sources and merged
together. One of my partner’s mothers had the idea of a picture where the eyes
in the picture would follow you wherever you went. Not a bad idea in our
opinion, although slightly creepy. So we ran with it and combined our former
idea of using a device as a drawing tool to a pointing tool. Not that far of a
jump in our opinion. Thus we came up with a system where the camera looks for a
laser pointers bright dot on a surface. Where that dot was located would be
where the creepy eyes of our picture would be. It worked . . . for the most
part. Initially we used a library called Mayron for the image analysis but we
ran into limitations. The library could only see certain colors and would see
every one of the pixels currently that color. A problem when a laser pointers
dot generally looks like white. The program would find all pixels with white
and essentially crash. This wasn’t going to work.
Our last and final iteration was only a natural step to take
from iteration #2. We wanted the eye of the portraits to follow people so we
need some software that could recognize people. Turns out there is a library
called openCV that has a facial recognition feature embedded in it. This was
perfect! We implemented it in so that the eye would follow a face walking by
the image and we had our final product.
Well it wasn’t quiet that easy. openCV is a great piece of
software that has been adapted and used on many different projects, programs
and operating systems. It is very popular in image processing and helped us
tremendously but not without some headaches. First we found that importing the
openCV library into processing on a PC it’s close to impossible. Further its
not possible on a 64-bit machine which is what mine is. Fortunately it is very
easy to use with a Mac and so we used all Mac’s to complete the project. We
also wanted a nice variation of portraits to be shown show we made a slide show feature with a fade in and out. This works perfectly creating the virtual art galllery feel that we were looking for with a special, creepy modification. Now we have the full effect.
Together as a team we completed this very complex and ever changing projcet. I have to give full credit to my teammates for all their hard work. I personally did all of the eye placement and work to get them to match up with the pictures that my partner edited for eye holes. It was a fun project and a creepy outcome. Just picture this in an art gallery. You would initially think its just a projection of a famous painting but the notice that it is watching you everywhere you go!
Code below:
import hypermedia.video.*;
import java.awt.Rectangle;
OpenCV opencv;
// contrast/brightness values
int contrast_value = 0;
int brightness_value = 0;
int X1;
int Y1;
int X2;
int Y2;
int opac=255;
int order = 0;
int m=0;
int last=0;
boolean active = false;
boolean X = false;
boolean next = false;
int xcenterlefteye;
int ycenterlefteye;
int xcenterrighteye;
int ycenterrighteye;
int eyewidth;
int eyeheight;
int leftedgelefteye;
int rightedgelefteye;
int leftedgerighteye;
int rightedgerighteye;
int topedgelefteye;
int bottomedgelefteye;
int topedgerighteye;
int bottomedgerighteye;
int X12;
int Y12;
int X22;
int Y22;
int xcenterlefteye2;
int ycenterlefteye2;
int xcenterrighteye2;
int ycenterrighteye2;
int eyewidth2;
int eyeheight2;
int leftedgelefteye2;
int rightedgelefteye2;
int leftedgerighteye2;
int rightedgerighteye2;
int topedgelefteye2;
int bottomedgelefteye2;
int topedgerighteye2;
int bottomedgerighteye2;
PImage imgMona;
PImage imgjohn;
PImage imgobama;
PImage imgfarm;
PImage imggw;
void setup() {
size( 1280, 800 );
opencv = new OpenCV( this );
opencv.capture( width, height); // open video stream
opencv.cascade( OpenCV.CASCADE_FRONTALFACE_ALT ); // load detection description, here-> front face detection : "haarcascade_frontalface_alt.xml"
imgMona = loadImage("Mona.png");
imgjohn = loadImage("john.png");
imgobama = loadImage("obama.png");
imgfarm = loadImage("farm.png");
imggw = loadImage("gw.png");
}
public void stop() {
opencv.stop();
super.stop();
}
void draw() {
background(0);
int h = height;
int w= width;
opencv.read();
//opencv.absDiff();
opencv.flip( OpenCV.FLIP_HORIZONTAL );
print("time " +m/1000+"\n");
print("order " +order+"\n");
print("next " +next+"\n");
print("active " +active+"\n\n\n\n");
m = millis()-last;
if(millis()>last+30000){
last=millis();
next=true;
}
if(next){
opac = opac-25;
print("-opac = " +opac+'\n');
}
if((opac<-25) && (active==false)){
next=false;
active = true;
order = order + 1;
}
if(active){
opac = opac + 25;
print("+opac = " +opac+'\n');
}
if ((opac > 255) && (active)){
active=false;
}
if(order==5){
order=0;
}
// proceed detection
Rectangle[] faces = opencv.detect( 1.2, 2, OpenCV.HAAR_DO_CANNY_PRUNING, 40, 40 );
// draw face area(s)
noFill();
//stroke(255,0,0);
noStroke();
for( int i=0; i<faces.length; i++ ) {
rect( faces[i].x, faces[i].y, faces[i].width, faces[i].height );
X1=(faces[i].x+(faces[i].width/2));
Y1=(faces[i].y+(faces[i].height/2));
X12=(faces[i].x+(faces[i].width/2));
Y12=(faces[i].y+(faces[i].height/2));
//print("X "+X1+ " Y "+ Y1+"\n");
}
ellipseMode(CENTER);
stroke(0);
if (order==0){
//Mona
xcenterlefteye = 605;
ycenterlefteye = 275;
xcenterrighteye = 685;
ycenterrighteye = 275;
eyewidth = 40;
eyeheight = 20;
leftedgelefteye = xcenterlefteye - eyewidth/2;
rightedgelefteye = xcenterlefteye + eyewidth/2;
leftedgerighteye = xcenterrighteye - eyewidth/2;
rightedgerighteye = xcenterrighteye + eyewidth/2;
topedgelefteye = ycenterlefteye - eyeheight/2;
bottomedgelefteye = ycenterlefteye + eyeheight/2;
topedgerighteye = ycenterrighteye - eyeheight/2;
bottomedgerighteye = ycenterlefteye + eyeheight/2;
//left eye
float x1 = map(X1, 0, width, leftedgelefteye, rightedgelefteye);
float y1 = map(Y1, 0, height, topedgelefteye, bottomedgelefteye);
//right eye
float x2 = map(X1, 0, width, leftedgerighteye, rightedgerighteye);
float y2 = map(Y1, 0, height, topedgerighteye, bottomedgerighteye);
ellipseMode(CENTER);
//eyes
fill(231,192,105,opac);
ellipse(xcenterlefteye, ycenterlefteye, eyewidth, eyeheight);
ellipse(xcenterrighteye, ycenterrighteye, eyewidth, eyeheight);
//pupils
fill(0,0,0,opac);
ellipse(x1, y1, 10, 10);
ellipse(x2, y2, 10, 10);
tint(255,opac);
image(imgMona,width/2-400,0);
}
if (order==1) {
//obama
xcenterlefteye = 640;
ycenterlefteye = 320;
xcenterrighteye = 710;
ycenterrighteye = 317;
eyewidth = 35;
eyeheight = 15;
leftedgelefteye = xcenterlefteye - eyewidth/2;
rightedgelefteye = xcenterlefteye + eyewidth/2;
leftedgerighteye = xcenterrighteye - eyewidth/2;
rightedgerighteye = xcenterrighteye + eyewidth/2;
topedgelefteye = ycenterlefteye - eyeheight/2;
bottomedgelefteye = ycenterlefteye + eyeheight/2;
topedgerighteye = ycenterrighteye - eyeheight/2;
bottomedgerighteye = ycenterlefteye + eyeheight/2;
//left eye
float x1 = map(X1, 0, width, leftedgelefteye, rightedgelefteye);
float y1 = map(Y1, 0, height, topedgelefteye, bottomedgelefteye);
//right eye
float x2 = map(X1, 0, width, leftedgerighteye, rightedgerighteye);
float y2 = map(Y1, 0, height, topedgerighteye, bottomedgerighteye);
ellipseMode(CENTER);
//eyes
fill(255,255,255,opac);
ellipse(xcenterlefteye, ycenterlefteye, eyewidth, eyeheight);
ellipse(xcenterrighteye, ycenterrighteye, eyewidth, eyeheight);
//pupils
fill(0,0,0,opac);
ellipse(x1, y1, 7, 7);
ellipse(x2, y2, 7, 7);
tint(255,opac);
image(imgobama, (width/2)-180, (height/2)-250);
}
if(order==2){
//john
xcenterlefteye = 520;
ycenterlefteye = 373;
xcenterrighteye = 670;
ycenterrighteye = 373;
eyewidth = 50;
eyeheight = 30;
leftedgelefteye = xcenterlefteye - eyewidth/2;
rightedgelefteye = xcenterlefteye + eyewidth/2;
leftedgerighteye = xcenterrighteye - eyewidth/2;
rightedgerighteye = xcenterrighteye + eyewidth/2;
topedgelefteye = ycenterlefteye - eyeheight/2;
bottomedgelefteye = ycenterlefteye + eyeheight/2;
topedgerighteye = ycenterrighteye - eyeheight/2;
bottomedgerighteye = ycenterlefteye + eyeheight/2;
//left eye
float x1 = map(X1, 0, width, leftedgelefteye, rightedgelefteye);
float y1 = map(Y1, 0, height, topedgelefteye, bottomedgelefteye);
//right eye
float x2 = map(X1, 0, width, leftedgerighteye, rightedgerighteye);
float y2 = map(Y1, 0, height, topedgerighteye, bottomedgerighteye);
ellipseMode(CENTER);
//eyes
fill(255,209,189,opac);
ellipse(xcenterlefteye, ycenterlefteye, eyewidth, eyeheight);
ellipse(xcenterrighteye, ycenterrighteye, eyewidth, eyeheight);
//pupils
fill(0,0,0,opac);
ellipse(x1, y1, 13, 13);
ellipse(x2, y2, 13, 13);
tint(255,opac);
image(imgjohn, (width/2)-221, (height/2)-300);
}
if(order==3){
//farm
//eyes # 1
xcenterlefteye = 485;
ycenterlefteye = 276;
xcenterrighteye = 525;
ycenterrighteye = 276;
eyewidth = 20;
eyeheight = 9;
leftedgelefteye = xcenterlefteye - eyewidth/2;
rightedgelefteye = xcenterlefteye + eyewidth/2;
leftedgerighteye = xcenterrighteye - eyewidth/2;
rightedgerighteye = xcenterrighteye + eyewidth/2;
topedgelefteye = ycenterlefteye - eyeheight/2;
bottomedgelefteye = ycenterlefteye + eyeheight/2;
topedgerighteye = ycenterrighteye - eyeheight/2;
bottomedgerighteye = ycenterlefteye + eyeheight/2;
//left eye
float x1 = map(X1, 0, width, leftedgelefteye, rightedgelefteye);
float y1 = map(Y1, 0, height, topedgelefteye, bottomedgelefteye);
//right eye
float x2 = map(X1, 0, width, leftedgerighteye, rightedgerighteye);
float y2 = map(Y1, 0, height, topedgerighteye, bottomedgerighteye);
ellipseMode(CENTER);
//eyes
fill(205,205,205,opac);
ellipse(xcenterlefteye, ycenterlefteye, eyewidth, eyeheight);
ellipse(xcenterrighteye, ycenterrighteye, eyewidth, eyeheight);
//pupils
fill(0,0,0,opac);
ellipse(x1, y1, 4, 4);
ellipse(x2, y2, 4, 4);
//////////////////////////////////
//eyes # 2
xcenterlefteye2 = 730;
ycenterlefteye2 = 210;
xcenterrighteye2 = 785;
ycenterrighteye2 = 210;
eyewidth2 = 20;
eyeheight2 = 10;
leftedgelefteye2 = xcenterlefteye2 - eyewidth2/2;
rightedgelefteye2 = xcenterlefteye2 + eyewidth2/2;
leftedgerighteye2 = xcenterrighteye2 - eyewidth2/2;
rightedgerighteye2 = xcenterrighteye2 + eyewidth2/2;
topedgelefteye2 = ycenterlefteye2 - eyeheight2/2;
bottomedgelefteye2 = ycenterlefteye2 + eyeheight2/2;
topedgerighteye2 = ycenterrighteye2 - eyeheight2/2;
bottomedgerighteye2 = ycenterlefteye2 + eyeheight2/2;
//left eye
float x12 = map(X12, 0, width, leftedgelefteye2, rightedgelefteye2);
float y12 = map(Y12, 0, height, topedgelefteye2, bottomedgelefteye2);
//right eye
float x22 = map(X12, 0, width, leftedgerighteye2, rightedgerighteye2);
float y22 = map(Y12, 0, height, topedgerighteye2, bottomedgerighteye2);
ellipseMode(CENTER);
//eyes
fill(205,205,205,opac);
ellipse(xcenterlefteye2, ycenterlefteye2, eyewidth2, eyeheight2);
ellipse(xcenterrighteye2, ycenterrighteye2, eyewidth2, eyeheight2);
//pupils
fill(0,0,0,opac);
ellipse(x12, y12, 4, 4);
ellipse(x22, y22, 4, 4);
tint(255,opac);
image(imgfarm, (width/2)-301, (height/2)-360);
}
if(order==4){
//gw
xcenterlefteye = 556;
ycenterlefteye = 332;
xcenterrighteye = 630;
ycenterrighteye = 333;
eyewidth = 30;
eyeheight = 15;
leftedgelefteye = xcenterlefteye - eyewidth/2;
rightedgelefteye = xcenterlefteye + eyewidth/2;
leftedgerighteye = xcenterrighteye - eyewidth/2;
rightedgerighteye = xcenterrighteye + eyewidth/2;
topedgelefteye = ycenterlefteye - eyeheight/2;
bottomedgelefteye = ycenterlefteye + eyeheight/2;
topedgerighteye = ycenterrighteye - eyeheight/2;
bottomedgerighteye = ycenterlefteye + eyeheight/2;
//left eye
float x1 = map(X1, 0, width, leftedgelefteye, rightedgelefteye);
float y1 = map(Y1, 0, height, topedgelefteye, bottomedgelefteye);
//right eye
float x2 = map(X1, 0, width, leftedgerighteye, rightedgerighteye);
float y2 = map(Y1, 0, height, topedgerighteye, bottomedgerighteye);
ellipseMode(CENTER);
//eyes
ellipse(xcenterlefteye, ycenterlefteye, eyewidth, eyeheight);
ellipse(xcenterrighteye, ycenterrighteye, eyewidth, eyeheight);
//pupils
fill(0,0,0,opac);
ellipse(x1, y1, 6, 6);
ellipse(x2, y2, 6, 6);
tint(255,opac);
image(imggw, (width/2)-302, (height/2)-250);
}
if(key=='o'){
tint(255,125);
image( opencv.image(), 0,0, displayWidth, displayHeight);
}
if ((key=='z')){
X = false;
}
if ((key=='x')){
X = true;
}
if (X){
fill(255);
noStroke();
quad(X1-10,Y1+10,X1-7,Y1+10,X1+10,Y1-10,X1+7,Y1-10);
quad(X1+10,Y1+10,X1+7,Y1+10,X1-10,Y1-10,X1-7,Y1-10);
}
}
or link to project:
https://www.dropbox.com/s/flxhx7wlji4ofxm/face_detectionE2.pde