This is my first post and my first processing script beyond tinkering with an occasional sample. It's an insignificant contribution compared to some of the treasures created with this marvelous tool; but none the less I felt the need to share it (besides it's nice to save it to the "cloud" even if in just forum post form). I used the script located
here as a starting point, so thank you for the lesson
Daniel.
It is designed to work with as many as nine webcams, but I only have tested it with three (if anyone has a chance to test it with more please let me know the results). It is also designed to support an external text file for properties, and errors if the file isn't found (haven't bothered learning how to error check that). It seems to be a processor hog too, but results have been pleasing. Anyone have a tip on how to remedy that? One last design flaw/misfortune; I couldn't find a quick easy way to have separate windows for each webcam feed and didn't want to bother with creating a dynamic window with each cam in it just yet (maybe in version 2.0 or better yet 10.0), so you simply use the number keys to select between webcam feeds.
import processing.video.*;
//Default Properties float threshold=300; int picdelay=2000; int winwidth=640; int winheight=480; int startdelay=0; int cameracount=9; int nosettings=0; String cams[]=Capture.list(); int maxcam=cams.length;
//Runtime Vars int activecam=1; String activecammsg = ""; int timer; int today = day(); Capture[] video; PImage[] prevFrame; int[] picidx;
void setup() { size(winwidth,winheight); _loadproperties(); //Load Properties from text file if (cameracount>maxcam){ cameracount=maxcam; } video = new Capture[cameracount]; prevFrame = new PImage[cameracount]; picidx = new int[cameracount]; for (int x=0;x<cameracount;x++) { prevFrame[x]=createImage(width,height,RGB); //Create PreviousFrame Bucket for Camera x of y video[x]=new Capture(this, width, height, 30); //Create Video Capture Object for Camera x of y if (nosettings==0){ video[x].settings(); //Open Camera Settings Applet for Init } } timer = millis(); frame.setTitle("Webcam Motion Detector - Camera " + activecam + " of " + cameracount); }
for (int i=0;i<cameracount;i++) { //Iterate through cameras if (video[i].available()) { //If Camera is Not Busy then Capture Previous Frame and New Frame prevFrame[i].copy(video[i],0,0,video[i].width,video[i].height,0,0,video[i].width,video[i].height); // Before we read the new frame, we always save the previous frame for comparison! prevFrame[i].updatePixels(); video[i].read(); }
if (i==(activecam-1)) { //Display Active Camera loadPixels(); }
video[i].loadPixels(); prevFrame[i].loadPixels();
for (int x = 0; x < video[i].width; x ++ ) { //Loop through pixels to detect motion for (int y = 0; y < video[i].height; y ++ ) { int loc = x + y*video[i].width; color current = video[i].pixels[loc]; color previous = prevFrame[i].pixels[loc];
pixels[loc] = current; //Set Display Window Pixels to Current Frame
int milliseconds = (millis() - timer); if (milliseconds >= picdelay) { //If Past Picture Delay Then Check for Motion if (diff > threshold) { //If Color Difference is Greater Than Threshold then Save Picture timer = millis(); int dy = day(); int mn = month(); int yr = year(); int now = dy; if (today!=now) { picidx[i]=1; //Increment picture index } String file = nf(mn,2); file += nf(dy,2); file += nf(yr,2); file += "\\"; video[i].save(file + "cam" + i + "_" + picidx[i] + ".JPG"); //Save Picture picidx[i]+=1; } } } } if (i==(activecam-1)) { //Display Active Camera updatePixels(); } } }
void keyPressed() { //Camera display Selection via Keyboard Numbers if ((keyCode>=49)&&(keyCode<=57)){ int var = keyCode-48; if (var<=cameracount) { activecam=var; frame.setTitle("Webcam Motion Detector - Camera " + activecam + " of " + cameracount); } } if (keyCode==27){ _abort(); // key=0; } }
void _loadproperties(){ //Read properties from text file String properties[]=loadStrings("properties.txt"); int arrlen = properties.length; if (boolean(arrlen)) { for (int x=0;x<arrlen;x++){ _loadproperty(properties[x]); } } }
void _loadproperty(String prop) { //Set default varible from property String values[]=split(prop,"="); int arrlen = values.length; if (values[0].equals("threshold")==true) { threshold=float(values[1]); } if (values[0].equals("picdelay")==true) { picdelay=int(values[1]); } if (values[0].equals("winwidth")==true) { winwidth=int(values[1]); } if (values[0].equals("winheight")==true) { winheight=int(values[1]); } if (values[0].equals("startdelay")==true) { startdelay=int(values[1]); } if (values[0].equals("cameracount")==true) { cameracount=int(values[1]); } if (values[0].equals("nosettings")==true) { nosettings=int(values[1]); } }
void _abort() { for (int i=0;i<cameracount;i++) { //Iterate through cameras delay(picdelay/2); if (video[i].available()!=true) { do { delay(picdelay/2); } while (video[i].available()!=true); } video[i].stop(); } }