Februar 26, 2012
Nach dem Einlesen der Videodaten in Processing galt es sich mit einem einfachen Color-Tracking vertraut zu machen. Ich habe zwei Color-Trackings integriert, je für einen Farbpunkt. Mit diesen zwei Punkten habe ich verschiedene Brillen und Schnurrbärte platziert, die ich mit Tasten auswechseln konnte. Da ich zwei Farbpunkte im Bild analysiere, konnte ich auch die Skalierung (durch Abstände der beiden Punkte) und Rotation (Winkel des Vektors zwischen den beiden Punkten) für die Objekte integrieren. Wenn ich mich von der Webcam entferne, dann werden auch die Objekte kleiner, und wenn ich den Kopf drehe, dann drehen sich auch die Brille und der Schnauz entsprechend.Processing
Main
PImage myImage; PImage imgmoustache; PImage imgglasses; import processing.opengl.*; float mouseInputX; float zoom; PVector startPos = new PVector(); PVector endPos = new PVector(); PVector startPosDir = new PVector(); ArrayList data= new ArrayList(); String[] imagesMoustaches = { "moustache.png", "moustache2.png", "moustache3.png" }; String[] imagesGlasses = { "glasses.png", "glasses2.png" }; int imageIndex=0; int imageIndexG=0; int mouseClicks=0; import processing.video.*; Capture video; color trackColor; color trackColor2; float rotation; void setup() { smooth(); // default tracking colors trackColor = color(204,204,0); trackColor2 = color(0,204,0); // default images imgmoustache = loadImage(imagesMoustaches[imageIndex]); imgglasses = loadImage(imagesGlasses[imageIndexG]); video = new Capture(this,800,600,12); if (video.available()) { video.read(); } myImage = video; reset(); size(800, 600); //, OPENGL } void reset() { data= new ArrayList(); if (video.available()) { video.read(); } myImage = video; myImage.loadPixels(); } void draw() { background(0); reset(); // COLOR TRACKING // Before we begin searching, the "world record" for closest color is set to a high number that is easy for the first pixel to beat. float worldRecord = 500; float worldRecord2 = 500; // XY coordinate of closest color int closestX = 0; int closestY = 0; int closestX2 = 0; int closestY2 = 0; // Loop through every pixel for (int x = 0; x < myImage.width; x++ ) { // We can get the length of the pixels array just like with any array. for (int y = 0; y < myImage.height; y++ ) { int loc = (x-myImage.width+1)*-1 + y * myImage.width; float mouseDistance = (width/2)-mouseX; startPos.set(mouseX,mouseY,0); endPos.set(width/2,height/2,0); PVector dir = PVector.sub(endPos,startPos); mouseDistance = dir.mag(); startPos.set(mouseX,mouseY,0); endPos.set(x,y,0); PVector dir2 = PVector.sub(endPos,startPos); float mouseDistanceCircle = dir2.mag(); // What is current color color currentColor = video.pixels[loc]; float r1 = red(currentColor); float g1 = green(currentColor); float b1 = blue(currentColor); float r2 = red(trackColor); float g2 = green(trackColor); float b2 = blue(trackColor); float rr2 = red(trackColor2); float gg2 = green(trackColor2); float bb2 = blue(trackColor2); // Using euclidean distance to compare colors float d = dist(r1,g1,b1,r2,g2,b2); // We are using the dist( ) function to compare the current color with the color we are tracking. float d2 = dist(r1,g1,b1,rr2,gg2,bb2); // We are using the dist( ) function to compare the current color with the color we are tracking. // If current color is more similar to tracked color than // closest color, save current location and current difference if (d < worldRecord) { worldRecord = d; closestX = x; closestY = y; } if (d2 < worldRecord2) { worldRecord2 = d2; closestX2 = x; closestY2 = y; } myImage.updatePixels(); } } pushMatrix(); scale(-1.0, 1.0); image(myImage,-1*myImage.width,0); popMatrix(); // ROTATION startPos.set(closestX, closestY, 0); endPos.set(closestX2, closestY2, 0); PVector dir = PVector.sub(endPos, startPos); //float mouseDistance = dir.mag(); startPosDir.set(closestX-closestX2, closestY-closestY2, 0); // angle of letter to mouse position float rotation = PVector.angleBetween(endPos,startPosDir); // get cross vector to determine direction (in which half circle) to complete 360 deg PVector v3 = startPos.cross(endPos); if (v3.z>0) { rotation = radians(360-degrees(rotation)); } rotation = radians(degrees(rotation)-60); if (worldRecord < 100) { float birdHeight = dist(closestX, closestY, 0, closestX2, closestY2, 0); float zoom = birdHeight/130; // image moustache imageMode(CENTER); pushMatrix(); translate(closestX, closestY); rotate(rotation); image(imgmoustache, 0, 0, imgmoustache.width/2*zoom, imgmoustache.height/2*zoom); popMatrix(); // image glasses pushMatrix(); translate(closestX2, closestY2); rotate(rotation); translate(0, imgglasses.height/3); image(imgglasses, 0, 0, imgglasses.width*zoom*0.75, imgglasses.height*zoom*0.75); popMatrix(); imageMode(CORNER); } } void mousePressed() { // pick color with mouse clicks loadPixels(); int loc = mouseX + mouseY * myImage.width; color tmp = color(red(pixels[loc]),green(pixels[loc]),blue(pixels[loc])); if (mouseClicks==0) { //mouseClicks++; trackColor = tmp; println(red(pixels[loc])+":"+green(pixels[loc])+":"+blue(pixels[loc])); //mouseClicks++; } if (mouseClicks==1) { trackColor2 = tmp; //mouseClicks=0; } } void keyPressed() { switch(key) { // laod next moustache case 'a': imageIndex++; if (imageIndex>=imagesMoustaches.length) imageIndex=0; imgmoustache = loadImage(imagesMoustaches[imageIndex]); reset(); break; // load next glasses case 's': imageIndexG++; if (imageIndexG>=imagesGlasses.length) imageIndexG=0; imgglasses = loadImage(imagesGlasses[imageIndexG]); reset(); break; // save screenshot case 'p': save("screen/screen_"+year()+"-"+month()+""+day()+"_"+hour()+"-"+minute()+"-"+second()); break; default: break; } // switch }