Last active
April 11, 2016 17:40
-
-
Save GalNissim/1d555f61658d616d84a248fc0ac4ee85 to your computer and use it in GitHub Desktop.
Face bubbles - Pixel by Pixel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import gab.opencv.*; //<>// | |
import processing.video.*; | |
import java.awt.*; | |
Capture cam; | |
OpenCV opencv; | |
int R, G, B, A; | |
Bubble[] bubbles = new Bubble[0]; | |
Bubble [] backgroundBubbles = new Bubble[0]; | |
int randPosX; | |
int randPosY; | |
int radios, minR, maxR; | |
int faceX =0, faceY, faceWidth, faceHeight; | |
int maxNumOfBubbles = 100; | |
int lastFacePosX = 0, lastFacePosY = 0; | |
int scl = 2; | |
void setup() { | |
size( 720, 480); | |
minR =20; | |
maxR = 100; | |
smooth(); | |
//WebCam | |
//String[] cameras = Capture.list(); | |
//if (cameras.length == 0) { | |
// //println("There are no cameras available for capture."); | |
// exit(); | |
//} else { | |
//println("Available cameras:"); | |
//for (int i = 0; i < cameras.length; i++) { | |
// //println(cameras[i]); | |
//} | |
//cam = new Capture(this, cameras[0]);- ask guy | |
cam = new Capture(this, width, height); | |
opencv = new OpenCV(this, width, height); | |
opencv.loadCascade("haarcascade_frontalface_alt2.xml"); | |
//opencv.loadCascade("lbpcascade.xml"); | |
cam.start(); | |
//} | |
} | |
void draw() { | |
//scale(2);//face | |
// draw live feed from the webcam | |
if (cam.available()) { | |
cam.read(); | |
opencv.loadImage(cam); | |
image(cam, 0, 0); | |
//background(0); | |
/// | |
noFill(); | |
stroke(0, 255, 0); | |
strokeWeight(3); | |
//Rectangle[] faces = new Rectangle[0]; | |
Rectangle[] faces = opencv.detect(); | |
println(faces.length); | |
for (int i = 0; i < faces.length; i++) { | |
int diff_x = faceX-faces[i].x; | |
int diff_y = faceX-faces[i].x; | |
//if (faces[i].width*faces[i].height < 2500) continue; | |
faceX = faces[i].x; | |
faceY = faces[i].y; | |
faceWidth = faces[i].width; | |
faceHeight = faces[i].height; | |
//println(faceWidth*faceHeight); | |
if (abs(diff_x) >10 && abs(diff_y) >10 || bubbles.length==0) { | |
generateBubbles(faceX, faceY, faceWidth, faceHeight); | |
//generateBubbles(0,0, width, height); | |
} | |
//break; | |
} | |
} | |
cam.loadPixels(); //load the pixels array of the video | |
loadPixels(); //load the pixels array of the window | |
for (int i = 0; i<bubbles.length; i++) { | |
bubbles[i].drawBubble(); | |
} | |
for (int i = 0; i<backgroundBubbles.length; i++) { | |
backgroundBubbles[i].drawBubble(); | |
} | |
updatePixels(); | |
cam.updatePixels(); | |
} | |
void generateBubbles(int faceX, int faceY, int faceWidth, int faceHeight) { | |
bubbles = new Bubble[0]; | |
for (int j = 0; j<maxNumOfBubbles; j++) { | |
randPosX = (int)random(faceX, faceX+ faceWidth); | |
randPosY = (int)random(faceY, faceY+faceHeight); | |
PxPGetPixel(randPosX, randPosY, cam.pixels, width); | |
bubbles = (Bubble[])append(bubbles, new Bubble(randPosX, randPosY)); //create a new bubble and add to the array | |
} | |
} | |
class Bubble { | |
int x0, y0, sRadius; | |
Bubble(int _posX, int _posY) { | |
x0 = _posX; | |
y0 = _posY; | |
sRadius =(int)random(minR, maxR); | |
} | |
void drawBubble() { | |
//int num = floor(sRadius/sqrt(2)); | |
int num = floor(sRadius/sqrt(2)); | |
for (int i = x0-num; i<=x0+num; i++) { | |
for (int j = y0-num; j<=y0+num; j++) { | |
///sphere projection values | |
int pX, pY, qX, qY; | |
//Write the point in a coordinate system centered at the center of the sphere (x0,y0,z0) | |
pX = i-x0; | |
pY = j-y0; | |
// Compute the length of this vector | |
int pNorm = (int)sqrt(sq(pX) +sq(pY)); | |
//Scale the vector so that it has length equal to the radius of the sphere | |
// pNorm is the distance between the center and the pixel | |
if (pNorm > num) continue; | |
// make sure to consider the case of pNorm == 0. | |
if (pNorm == 0) { | |
qX = x0; | |
qY = y0; | |
} else { | |
qX = (sRadius/pNorm)*pX+x0; | |
qY = (sRadius/pNorm)*pY+y0; | |
} | |
//constrain the bubbles so they will be in the screen borders | |
qX = constrain(qX, 0, width-1); | |
qY = constrain(qY, 0, height-1); | |
int newI = constrain(i, 0, width-1); | |
int newJ = constrain(j, 0, height-1); | |
PxPGetPixel(qX, qY, cam.pixels, width); | |
PxPSetPixel (newI, newJ, R, G, B, 255, pixels, width); // set the RGB of our to screen | |
} | |
} | |
} | |
} | |
// our function for getting color components , it requires that you have global variables | |
// R,G,B (not elegant but the simples way to go, see the example PxP methods in object for | |
// a more elegant solution | |
void PxPGetPixel(int x, int y, int[] pixelArray, int pixelsWidth) { | |
int thisPixel = pixelArray[x+y*pixelsWidth]; // getting the colors as an int from the pixels[] | |
A = (thisPixel >> 24) & 0xFF; // we need to shift and mask to get each component alone | |
R = (thisPixel >> 16) & 0xFF; // this is faster than calling red(), green() , blue() | |
G = (thisPixel >> 8) & 0xFF; | |
B = thisPixel & 0xFF; | |
} | |
//our function for setting color components RGB into the pixels[] , we need to efine the XY of where | |
// to set the pixel, the RGB values we want and the pixels[] array we want to use and it's width | |
void PxPSetPixel(int x, int y, int r, int g, int b, int a, int[] pixelArray, int pixelsWidth) { | |
a =(a << 24); | |
r = r << 16; // We are packing all 4 composents into one int | |
g = g << 8; // so we need to shift them to their places | |
color argb = a | r | g | b; // binary "or" operation adds them all into one int | |
pixelArray[x+y*pixelsWidth]= argb; // finaly we set the int with te colors into the pixels[] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment