This seems to be the fastest, most accurate version yet:
java code:
public boolean detect(byte[] data, int width, int height) {
// half width and height to reduce loops
int half_height = height / 2;
int half_width = width / 2;
// boolean map to hold our threshold pic
boolean[] map = new boolean[half_height * half_width];
for (int y = 0, i = 0, ii = 0; y < half_height; y++) {
for (int x = 0; x < half_width; x++, i+=2,ii++) {
int l = (0xff & ((int) data[i])) - 16;
if (previous_frame != null) {
int pl = (0xff & ((int) previous_frame[i])) - 16;
int d = pl;
// merge 50% of each frame, lets not use division
d = ((int)((5 * l) + (5 * d))-(d*10));
// if theres a negative diff, lets reverse it
if (d < 0){
d = -d;
}
//build up our threshold map
map[ii] = d > 150;
}
}
}
previous_frame = data;
boolean erode = false;
for (int y = 0, i = 0; y < half_height; y++) {
for (int x = 0; x < half_width; x++, i++) {
erode = false;
if (map[i]) {
loop through the pixels around it
for (int yi=-2;yi<=2;yi++){
for (int xi=-2;xi<=2;xi++){
int px = (y+yi) * half_width + (x+xi);
if (px >= 0 && px < map.length) {
// if a pixel is eroded, carry on
if (!map[px]) {
erode = true;
break;
}
}
}
}
// if no pixels around this pixel have been eroded, we know there's probably some motion
if (!erode) {
return true;
}
}
}
}
return false;
}
I'm getting plenty of frames and I'm eroding noise. I might try to fit my 'normalize' code back in now, too, so I can make sure it works well at night.
|