Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 14 Next »

Auf dieser Seite werden ein paar einfach Computer Vision Algorithmen gezeigt und erklärt.

Background Subtraction

Wollen wir beispielsweise Bewegung auf einem Bild erkennen, so ist es hilfreich eine Art “Green-Screen” zu haben, welcher dann nur die Bereiche zeichnet, welche sich verändern. Dies erreichen wir mit einem sog. Background-Removal oder Background-Substraction. Dazu vergleichen wir ein statisches Referenzbild mit einem Live-Bewegtbild. Wenn die Differenz zwischen beiden Bildern (und damit die Differenz der Farbwerte an der Selben Stelle) grösser ist als ein bestimmter Schwellenwert, können wir davon ausgehen, dass an diesem Punkt Bewegung stattfindet. Leider muss man als Abstrich sagen, dass die automatische Helligkeitskorrektur der iSight Kamera sich schlecht für diese Methode auswirkt.

Beispiel
import processing.video.*;
Capture video;

PImage backgroundImage;
float threshold = 20;

void setup() {
  size(640, 480);
  video = new Capture(this, width, height, 30);
  video.start();
  backgroundImage = createImage(video.width, video.height, RGB);
}

void draw() {
  if (video.available()) {
    video.read();
  }
  
  loadPixels();
  video.loadPixels(); 
  backgroundImage.loadPixels();
  
  for (int x=0; x < video.width; x++) {
    for (int y=0; y < video.height; y++) {
      int loc = x + y * video.width; 
      color fgColor = video.pixels[loc]; 
      
      color bgColor = backgroundImage.pixels[loc];
      
      float r1 = red(fgColor);
      float g1 = green(fgColor);
      float b1 = blue(fgColor);
      float r2 = red(bgColor);
      float g2 = green(bgColor);
      float b2 = blue(bgColor);
      float diff = dist(r1, g1, b1, r2, g2, b2);
      
      if (diff > threshold) {
        pixels[loc] = fgColor;
      } else {
        pixels[loc] = color(0); 
      }
    }
  }

  updatePixels();
}

void mousePressed() {  
  backgroundImage.copy(video, 0, 0, video.width, video.height, 0, 0, video.width, video.height);
  backgroundImage.updatePixels();
}

Hellster Punkt

Für die direkte Steuerung eines Interfaces kann es hilfreich sein, zu wissen, wo sich der hellste Punkt in einem Bild befindet. Dazu wird ein PVector erstellt und eine Variable, welche den jeweils hellsten Wert für das aktuelle Frame beinhaltet. Durch das Vergleichen der Helligkeitswerte im ganzen Frame kann sehr schnell der Hellste Punkt bestimmt werden.

Beispiel
import processing.video.*;
Capture video;

PVector brightestPoint = new PVector(0,0);

void setup() {
  size(640, 480);
  video = new Capture(this, width, height, 30);
  video.start();
}

void draw() {
  if (video.available()) {
    video.read();
  }

  float brightness = 0;

  for (int x=0; x < width; x++) {
    for (int y=0; y < height; y++) {
      int loc = x + y * width;
      color c = video.pixels[loc];

      if (brightness(c) > brightness) {
        brightness = brightness(c);
        brightestPoint.x = x;
        brightestPoint.y = y;
      }
    }
  }
  
  image(video, 0, 0);
  ellipse(brightestPoint.x, brightestPoint.y, 20, 20);
}

Farbtracking

Das Farbtracking ist eine sehr einfach Method um ein farbiges Objekt in einem Bild zu finden. Dazu wird einfach der Punkt im Bild gesucht der der festgelegtern Farbe am ähnlichsten ist.

Beispiel
import processing.video.*;
Capture video;

color trackColor; 

void setup() {
  size(640, 480);
  
  video = new Capture(this, width, height, 15);
  video.start();

  trackColor = color(255, 0, 0);
  smooth();
}

void draw() {
  if (video.available()) {
    video.read();
  }

  video.loadPixels();
  image(video, 0, 0);

  float worldRecord = 500; 

  int closestX = 0;
  int closestY = 0;
  
  PVector closestPoint = new PVector();
  
  for (int x=0; x < video.width; x++) {
    for (int y=0; y < video.height; y++) {
      int loc = x + y * video.width;
      color currentColor = video.pixels[loc];
      
      PVector currColorVec = new PVector(red(currentColor), green(currentColor), blue(currentColor));
      PVector trackColorVec = new PVector(red(trackColor), green(trackColor), blue(trackColor));
      float diff = currColorVec.dist(trackColorVec);
      
      if (diff < worldRecord) {
        worldRecord = diff;
        closestPoint.x = x;
        closestPoint.y = y;
      }
    }
  }

  if (worldRecord < 10) { 
    fill(trackColor);
    strokeWeight(4.0);
    stroke(0);
    ellipse(closestPoint.x, closestPoint.y, 50, 50);
  }
}

void mousePressed() {
  int loc = mouseX + mouseY * video.width;
  trackColor = video.pixels[loc];
}

Blob Detection

Die Blob Detection is schon ein komplexere Art von Algorithm, wo ein gesamtes Objekt (Blop) zu erkennen versucht wird.

Beispiel
import processing.video.*;
Capture video;

BlobDetector blobDetector;
color blobColor; 

void setup() {
  size(640, 480);

  video = new Capture(this, width, height, 15);
  video.start();
  
  blobDetector = new BlobDetector();
  blobColor = color(255, 0, 0);

  smooth();
}

void draw() {
  if (video.available()) {
    video.read();
  }
  
  video.loadPixels();
  
  // for black and white image
  // video.filter(THRESHOLD,0.1);
  image(video, 0, 0);
  
  blobDetector.findBlob(blobColor, 20); 
  blobDetector.drawBlob();
  blobDetector.drawBoundingBox();
  blobDetector.drawCenterOfMass();
}

void mousePressed() {
  int loc = mouseX + mouseY*video.width;
  blobColor = video.pixels[loc];
}

class BlobDetector {
  int blobPoints[][];
  int blobWeight = 0;
  PVector centerOfMass;

  BlobDetector() {
    blobPoints = new int[width][height];
    centerOfMass = new PVector(0, 0);
  }

  void findBlob(color blobColor, int threshold) {
    blobWeight = 0;

    for (int x = 0; x < width; x ++ ) {
      for (int y = 0; y < height; y ++ ) {
        int loc = x + y*width;
        color currentColor = video.pixels[loc];

        PVector currColorVec = new PVector(red(currentColor), green(currentColor), blue(currentColor));
        PVector trackColorVec = new PVector(red(blobColor), green(blobColor), blue(blobColor));
        float diff = currColorVec.dist(trackColorVec);

        if (diff < threshold) {
          blobPoints[x][y] = 1;
          blobWeight++;
        } else {
          blobPoints[x][y] = 0;
        }
      }
    }
    
    text(blobWeight, 20, 20);
  }

  void drawBlob() {
    if (blobWeight > 200) {
      for (int x = 0; x < width; x ++ ) {
        for (int y = 0; y < height; y ++ ) {
          if (blobPoints[x][y] == 1) {
            strokeWeight(5);
            stroke(255, 0, 0);
            point(x, y);
          }
        }
      }
    }
  }

  void drawBoundingBox() {
    PVector A = new PVector(width, height);
    PVector B = new PVector(0, 0);
    for (int x = 0; x < width; x ++ ) {
      for (int y = 0; y < height; y ++ ) {
        if (blobPoints[x][y] == 1) {
          if (y < A.y)
            A.y = y;
          if (y > B.y)
            B.y = y;
          if (x < A.x)
            A.x = x;
          if (x > B.x)
            B.x = x;
        }
      }
    }

    strokeWeight(1);
    noFill();
    rect(A.x, A.y, B.x-A.x, B.y-A.y);
    text("A "+A.x+","+A.y, A.x, A.y);
    text("B "+B.x+","+B.y, B.x, B.y);
  }

  void drawCenterOfMass() {
    centerOfMass.set(0.0, 0.0, 0.0);

    for (int x = 0; x < width; x ++ ) {
      for (int y = 0; y < height; y ++ ) {
        if (blobPoints[x][y] == 1) {
          centerOfMass.x += x;
          centerOfMass.y += y;
        }
      }
    }
    
    centerOfMass.x /= blobWeight;
    centerOfMass.y /= blobWeight;

    noStroke();
    fill(255);
    ellipse(centerOfMass.x, centerOfMass.y, 10, 10);
  }
}

Weitere Informationen