// trackerDiff.pde // // part of the project 'demographic data in augmented reality' // http://digitaleinformationsarchitektur.m05.de // // 2003 michael zoellner // import processing.video.*; TrackerDiff t; boolean bgSet = false; int tolerance, count; float diff; PImage diffImage, bgImage; Capture capture; void setup() { size(240,180, P3D); noFill(); stroke(#FFFF00); background(255); capture = new Capture(this, 240, 180, 25); count = capture.width * capture.height; tolerance = 20; // treshold.. rbg+-value diff = width/capture.width; // relation between screensize and videosize // initialize the tracker t = new TrackerDiff(tolerance, capture.width, capture.height); } void captureEvent(Capture capture) { capture.read(); } void draw() { //background(0); //image(capture, 0, 0); // show video if (bgSet == true) { // compare the video image with the reference image // returns an array with x1, y1, x2, y2 (upper left and bottom right) int[] rectPoints = t.GetPixelDiff(capture, bgImage, diff); // returns an image of this area with alpha channel diffImage = t.GetPixelDiffImg(); if (diffImage.width > 0 && diffImage.height > 0) { tint(255, 100); fill(255, 5); rect(0,0,width,height); image(diffImage, rectPoints[0]*diff, rectPoints[1]*diff); } // draw a rect in this area //rect(rectPoints[0]*diff, rectPoints[1]*diff, (rectPoints[2]-rectPoints[0])*diff, (rectPoints[3]-rectPoints[1])*diff); } else { //image(capture, 0, 0); // show video } } void keyReleased() { // make a shot of the background -> reference image if (key == 'b') { bgImage = t.GetRefBackground(capture); bgSet = true; } } //////////////////////// import processing.core.*; public class TrackerDiff extends PApplet { int rCurrent, gCurrent, bCurrent; int rCurrent2, gCurrent2, bCurrent2; int rRef, gRef, bRef; int rRef2, gRef2, bRef2; int yMin, xMin; float rDiff, gDiff, bDiff; float rDiff2, gDiff2, bDiff2; PImage tempImg; int xMax = 0; int yMax = 0; public TrackerDiff(int tolerance, int quadWidth, int quadHeight) { this.currTolerance = tolerance; this.qw = quadWidth; this.qh = quadHeight; xMin = qw; yMin = qh; } public PImage GetRefBackground(PImage refBg) { // referenzbild anlegen und zurueckgeben //PImage rBg = new PImage(refBg.width, refBg.height); PImage rBg = createImage(refBg.width, refBg.height, ARGB); System.arraycopy(refBg.pixels,0,rBg.pixels,0,refBg.pixels.length-1); // spaeteres transparetes images der veraenderungen anlegen tempImg = createImage(refBg.width, refBg.height, ARGB); tempImg.smooth = true; return rBg; } public PImage GetPixelDiffImg() { // das in GetPixelDiff angelegte image wird zurueckgegeben (workaround) PImage cropTempImg = tempImg.get(xMin, yMin, xMax-xMin, yMax-yMin); return cropTempImg; } public int[] GetPixelDiff(PImage currentFrame, PImage rBg, float diff) { xMin = qw; yMin = qh; xMax = 0; yMax = 0; // aktuellen videoframe kopieren -> unveraenderte bereiche werden spaeter transparent gemacht System.arraycopy(currentFrame.pixels,0,tempImg.pixels,0,currentFrame.pixels.length-1); // veraenderungen finden for(int i=0; i < currentFrame.pixels.length; i++) { rCurrent = (currentFrame.pixels[i] >> 16) & 0xff; gCurrent = (currentFrame.pixels[i] >> 8) & 0xff; bCurrent = currentFrame.pixels[i] & 0xff; rRef = (rBg.pixels[i] >> 16) & 0xff; gRef = (rBg.pixels[i] >> 8) & 0xff; bRef = rBg.pixels[i] & 0xff; rDiff = rRef - rCurrent; gDiff = gRef - gCurrent; bDiff = bRef - bCurrent; int x = i % qw; int y = i / qw; if (rDiff > currTolerance || gDiff > currTolerance || bDiff > currTolerance) { // aesserste pixel berechnen -> rect if(x < xMin) xMin = x; if(y < yMin) yMin = y; if(x > xMax) xMax = x; if(y > yMax) yMax = y; tempImg.pixels[i] = currentFrame.pixels[i]; } else { // unveraenderte pixel tranparent setzen tempImg.pixels[i] = 0x00000000; } } //image (tempImg.get(xMin, yMin, xMax, yMax), 0, 0); int[] changedRect = {xMin*(int)diff, yMin*(int)diff, xMax*(int)diff, yMax*(int)diff}; return changedRect; } public int currTolerance, qw, qh; }