|
Author |
Topic: motion detection w/o JMyron? (Read 5309 times) |
|
sspboyd
|
motion detection w/o JMyron?
« on: Sep 8th, 2004, 5:53am » |
|
I am trying to test a method doing motion detection without using JMyron. JMyron is overkill for some of the projects I am working on. I am having trouble making it work. I am attempting to compare the current frame of video with the previous frame in a grid like fashion. So far this program reports that there are no differences whatsoever between the current frame and previous frames. I am not sure where this is going off the rails. Any help is much appreciated. Thanks, steve Code:float sensitivity; // sensitivity is a percentage of pixels changed boolean newFrame; // switch var for determining when a new frame is received BImage currFrame, prevFrame; // vars for holding the current and previous frames BImage currSubSection, prevSubSection; // vars for holding subsections being tested for motion void setup(){ size(320,240); sensitivity=0.01; newFrame=false; currSubSection=prevSubSection=new BImage(width/40,height/30); stroke(200); noFill(); beginVideo(320,240,30); } public void videoEvent(){ newFrame=true; } void loop(){ if(newFrame){ newFrame=false; if(currFrame==null){ currFrame=prevFrame=new BImage(width,height); // initalize these vars on the first run through currFrame=prevFrame=video; // set them both to the video source }else{ prevFrame=currFrame; //update prev frame currFrame=video; // update current frame int mc=0; // testing counter var to keep track of number of grid sections that have motion image(currFrame,0,0); // update display with current frame for(int y=0; y<40; y++){ // start looping through the video in a 40x30 grid for(int x=0; x<30; x++){ int cxLoc=x*(width/40); // x position on grid int cyLoc=y*(height/30); // y position on grid currSubSection.replicate(currFrame, cxLoc,cyLoc,cxLoc+40,cyLoc+30, 0,0,40,30); prevSubSection.replicate(prevFrame, cxLoc,cyLoc,cxLoc+40,cyLoc+30, 0,0,40,30); //test for motion if(motionTest(currSubSection, prevSubSection)==true){ rect(cxLoc,cyLoc,40,30); //draw rect to indicate motion mc++; // update motion counter println("motion is detected: "+mc); // more testing stuff } } } } } } boolean motionTest(BImage _prev, BImage _curr){ BImage prev=_prev; BImage curr=_curr; int diffCount=0; // counter for number of difference int numPixels=curr.pixels.length; // reads number of pixels in images for (int i=0; i<numPixels;i++){ if(curr.pixels[i]!=prev.pixels[i]){ // test for difference ( is this the best way of doing this? ) diffCount++; // if different, increment counter } } // println(diffCount); if(diffCount>sensitivity*numPixels){ // test to see if number of difference is 'significant' return true; }else{ return false; } } |
|
|
gmail.com w/ sspboyd username
|
|
|
fjen
|
Re: motion detection w/o JMyron?
« Reply #1 on: Sep 8th, 2004, 5:04pm » |
|
hmm. to my understanding the problem resides here: prevFrame=currFrame; //update prev frame currFrame=video; // update current frame you are not copying pixels here but are setting a reference .. means, prevFrame points to currFrame which is then set to point to video. so in the end prevFrame points to video as well ... clear? you should rather copy the pixel-arrays System.arraycopy(): http://java.sun.com/j2se/1.4.2/docs/api/java/lang/System.html
|
|
|
|
sspboyd
|
Re: motion detection w/o JMyron?
« Reply #2 on: Sep 8th, 2004, 6:12pm » |
|
i have replaced those two lines with the following code: Code:System.arraycopy(currFrame.pixels,0, prevFrame.pixels,0,prevFrame.pixels.length); //update prev frame System.arraycopy(video.pixels,0, currFrame.pixels,0,currFrame.pixels.length); //update curr frame |
| I am implementing this correctly? I am still getting the same result (no detection).
|
gmail.com w/ sspboyd username
|
|
|
lars
|
Re: motion detection w/o JMyron?
« Reply #3 on: Sep 8th, 2004, 8:14pm » |
|
I did a test for detecting motion comparing each frame to the previous - here is my code // pixelChange // by lars <http://www.larsjessen.dk> // Detects change in brightness from frame to frame // Created 1 Sep 2004 int xpos = 0; int ypos = 0; int captureWidth = 80; int captureHeight = 60; int[] pixelArray; Rectangle rectArray[]; boolean newFrame = false; int motionCounter; void setup() { size(800, 600); // Begin capturing video at 40 by 30 pixels at a 30 beginVideo(captureWidth, captureHeight, 20); pixelArray = new int[captureWidth*captureHeight]; framerate(20); } void videoEvent() { newFrame = true; } void loop() { if(newFrame) { int index = 0; for(int i=0; i<captureHeight; i++) { for(int ii=0; ii<captureWidth; ii++) { color c; int newPixel; newPixel = (int) brightness(video.pixels[index]); if(abs(newPixel-pixelArray[index]) > 50) { c = color(255,255,255); motionCounter = motionCounter + 1; } else { c = color(0,0,0); } pixelArray[index] = newPixel; noStroke(); fill(c); triangle(10*ii,10*i,10*ii+10,10*i,10*ii+5,10*i+10); index++; } } println("motion: " + motionCounter); motionCounter = 0; newFrame = false; } }
|
|
|
|
lars
|
Re: motion detection w/o JMyron?
« Reply #4 on: Sep 8th, 2004, 8:23pm » |
|
I did another type of motion tracking as well where I compare the current frames to a reference frame - you have to press the mouse to capture a reference image. Hope this helps /lars // pixelCompare // by lars <http://www.larsjessen.dk> // Compares the frame captures from the camera to a reference image. For a new reference image press the mouse // Created 1 Sep 2004 int xpos = 0; int ypos = 0; int captureWidth = 80; int captureHeight = 60; color[] pixelArray; boolean newFrame = false; int motionCounter = 0; void setup() { size(800, 600); beginVideo(captureWidth, captureHeight, 20); pixelArray = new int[captureWidth*captureHeight]; framerate(20); for(int i=0; i<(captureWidth*captureHeight); i++) { pixelArray[i] = video.pixels[i]; } } void videoEvent() { newFrame = true; } void loop() { if(newFrame) { int index = 0; for(int i=0; i<captureHeight; i++) { for(int ii=0; ii<captureWidth; ii++) { color c; int pixelCompare; pixelCompare = (int) ( abs( red(pixelArray[index]) - red(video.pixels[index])) + abs( green(pixelArray[index]) - green(video.pixels[index])) + abs( blue(pixelArray[index]) - blue(video.pixels[index])) ); if(pixelCompare > 50) { motionCounter = motionCounter + 1; c = color(255,255,255); } else { c = color(0,0,0); } noStroke(); fill(c); triangle(10*ii,10*i,10*ii+10,10*i,10*ii+5,10*i+10); index++; } } println("motion: " + motionCounter); motionCounter = 0; newFrame = false; } } void mousePressed() { for(int i=0; i<(captureWidth*captureHeight); i++) { pixelArray[i] = video.pixels[i]; } }
|
|
|
|
fjen
|
Re: motion detection w/o JMyron?
« Reply #5 on: Sep 9th, 2004, 12:00am » |
|
venner, jep syntax seems right. but you still have some of these double initiations in there: currSubSection=prevSubSection=new BImage(width/40,height/30); this line reads: create instance of BImage(size) and put it in prevSubSection _and_ currSubSection ... see? currFrame=prevFrame=new BImage(width,height); currFrame=prevFrame=video; here is an example of what's happening: Code:BImage t1, t2; boolean flip; void setup() { size(200,300); // set true to see difference // if (false) { // seperate instances of BImage // t1 = new BImage(width, height); t2 = new BImage(width, height); } else { // same instance in both variables // t1 = t2 = new BImage(width, height); } BGraphics bb = new BGraphics(width, height); bb.line(0,0,width,height); System.arraycopy(bb.pixels,0,t1.pixels,0,t1.pixels.length); bb.background(128); bb.line(0,height,width,0); System.arraycopy(bb.pixels,0,t2.pixels,0,t2.pixels.length); } void loop() { if (flip) image(t1,0,0); else image(t2,0,0); flip = !flip; delay(300); } |
| hope this helps ... best /F
|
|
|
|
sspboyd
|
Re: motion detection w/o JMyron?
« Reply #6 on: Sep 10th, 2004, 7:37pm » |
|
thanks very much for the help lars and fjen. I've got it working the way I want. Here's the code I am using. Code:float sensitivity; // sensitivity is a percentage of pixels changed boolean newFrame; // switch var for determining when a new frame is received color[] prevFrame; // vars for holding the current and previous frames void setup(){ size(320,240); sensitivity=0.24; newFrame=false; stroke(240); noFill();; prevFrame=new color[320*240]; beginVideo(320,240,30); framerate(30); } public void videoEvent(){ newFrame=true; } void loop(){ if(newFrame){ newFrame=false; image(video,0,0); // update display with current frame for(int y=0; y<30-1; y++){ // loop through video in 40x30 grid for(int x=0; x<40-1; x++){ // println(mtc++); int cxLoc=x*(320/40); // x position on grid int cyLoc=y*(240/30); // y position on grid if(motionTest(cxLoc,cyLoc,width/40,width/30)==true){ rect(cxLoc+4,cyLoc+4,(width/40)-2,(width/30)-2); //indicate motion } } } } } boolean motionTest(int srcX,int srcY,int tw, int th){ int dc=0; // counter to track number of differences color newPixel; for(int y=0;y<th;y++){ for(int x=0;x<tw;x++){ int srcPos=((srcY+y)*width)+(srcX+x); newPixel = video.pixels[srcPos]; if(abs(red(newPixel)-red(prevFrame[srcPos]))>25) dc++; prevFrame[srcPos]=newPixel; // update prevFrame w/ current pixel clr } } // test to see if number of difference is 'significant' if(dc>(sensitivity*(tw*th))){ return true; }else{ return false; } } |
|
|
gmail.com w/ sspboyd username
|
|
|
|