Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

05.2 Video Color Tracking Basic

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
}