...we may find the answers we seek. Or at least a cool way to do motion-ish tracking.
This makes the second time this week i've been researching something just for the hell of it and suddenly find a use for it a day later, altho I guess the rounding algorithm stuff did have an actual purpose. Oddly enough, the project i want to use it for was waiting for me to figure out some version of this little snippet. Originally I was thinking i was going to have to do it as a full on hand-tracking/skeletal tracking thing, but if I can figure out some smoothing, I think this'll work pretty nicely on its own. We're putting together a mini-installation at work, details of which I'll not spoil for you here, but should be fun...
I started wondering about frame differencing after repeated visits to
testwebcam.com (yes, it's SFW). Simple effect, but it looks really cool. Also a great way to approximate motion on a webcam stream. The initial implementation didn't take me too long, now I just have to implement some optical flow or maybe even just a cheap trailing-3 tap, who knows? Of course, you're welcome to solve that problem yourself if you wanna copy-paste this into your own copy of
processing and hit Ctrl-R...seriously, your copy of p5 looks a little lonely and unloved, you should do something with it...I did some tests with lerping and vector/distancing, but i think i'm going to need a real filter...
This is totally not a photoshop, run the sketch if you don't believe me...
One of these days I need to start seriously optimizing some (all) of these sketches and my
ofx projects. It's ok to suck out loud for now, but truth be told, I think i'm actually a better programmer than that. I mean, not that I'm a good programmer, i'm just decent enough not to make silly un-optimization mistakes. Eh, this one'll optimize itself out anyway me thinks, i imagine the filtering isn't going to be cheap...I also really need to start taking video...
//PREPARE YOURSELF FOR THE COMING OF 2.0
//GET GSVIDEOOOOkay it's actually not going to be
//that big of a transition.
import codeanticode.gsvideo.*;
PImage lastFrame;
GSCapture vStream;
int diff;
int thresh = 32;
ArrayList<PVector> dVals = new ArrayList();
PVector p_m;
PVector lastP;
void setup()
{
p_m = new PVector(0,0);
lastP = new PVector(0,0);
size(640, 480, P2D);
frameRate(30);
lastFrame = createImage(width,height,RGB);
vStream = new GSCapture(this, width, height);
vStream.start();
background(0);
}
void draw()
{
diff = 0;
loadPixels();
dVals.clear();
if(vStream.available())
{
vStream.read();
vStream.loadPixels();
lastFrame.loadPixels();
for (int x=0;x<width;x++)
{
for (int y=0;y<height;y++)
{
int i = y*width+x;
color c = vStream.pixels[i];
color l = lastFrame.pixels[i];
int c_r = int(red(c));
int c_g = int(green(c));
int c_b = int(blue(c));
int l_r = int(red(l));
int l_g = int(green(l));
int l_b = int(blue(l));
int d_r = max(0,(c_r-l_r)-thresh);
int d_g = max(0,(c_g-l_g)-thresh);
int d_b = max(0,(c_b-l_b)-thresh);
int d_s = d_r+d_g+d_b;
diff += d_s;
if(d_s>0)
{
dVals.add(new PVector(x,y));
}
pixels[i] = vStream.pixels[i];
lastFrame.pixels[i] = c;
}
}
}
updatePixels();
if(diff>0)
{
p_m = avgArrayList(dVals);
fill(255,255,255);
ellipse(p_m.x,p_m.y,40,40);
}
lastP = p_m;
}
PVector avgArrayList(ArrayList<PVector> arr)
{
float sumx=0;
float sumy=0;
for(int i=0;i<arr.size();i++)
{
PVector c = (PVector)arr.get(i);
sumx+=c.x;
sumy+=c.y;
}
return new PVector(sumx/arr.size(),sumy/arr.size());
}
void keyPressed()
{
if(key=='q')
{
thresh+=1;
if(thresh>128)
thresh=128;
}
if(key=='a')
{
thresh-=1;
if(thresh<8)
thresh=8;
}
}
void stop()
{
vStream.stop();
vStream.dispose();
}