Hmm. Moving over to the greyscale version causes a HUGE dip in FPS.
java code:
package com.mikeefranklin.birdcam;
import android.util.Log;
public class Detector {
int[] previous_frame;
public Detector() {
}
public boolean detect(byte[] data, int width, int height)
{
// between 18 and 25 fps here
int min = 255;
int max = 0;
final int[] pixels = new int[width*height];
for (int y = 0, yp = 0; y < height; y++) {
for (int x = 0; x < width; x++, yp++) {
int l = (0xff & ((int) data[yp])) - 16;
if (l < 0) l = 0;
pixels[yp] = (int)(l*2.55);
min = Math.min(min, pixels[yp]);
max = Math.max(max, pixels[yp]);
}
}
// we're at 5 FPS here
int[] diff_data;
if (previous_frame != null){
diff_data = new int[pixels.length];
}else {
diff_data = new int[0];
}
// normalize it to deal with low contrast
int dist = Math.max(1, max - min);
int i = 0;
boolean hasChange = false;
for(int y=0; y<height; y++){
for(int x=0; x<width; x++, i++){
int newgrey = ((pixels[i] - min) / dist) * 255;
pixels[i] = newgrey;
// if theres a previous frame, lets do a diff on it
if (previous_frame != null) {
// but first, lets morph 30% of the background in
diff_data[i] = ((int)(0.7*(pixels[i]) ) + (int)(0.3*(previous_frame[i]))) - previous_frame[i];
diff_data[i] = ( diff_data[i] < 0 ) ? -diff_data[i] : diff_data[i];
diff_data[i] = diff_data[i] > 40 ? 255 : 0;
if (diff_data[i] == 255) {
hasChange = true;
}
}
}
}
// down to 4 fps already
// save old frame, or return false here if theres no change at all yet
previous_frame = pixels;
if (previous_frame == null || !hasChange){
return false;
}
// if there's change, we'll erode any pixels that have a black pixel within 4 of itself
i = 0;
int size = 2;
for(int y=0; y<height; y++){
for(int x=0; x<width; x++,i++){
boolean erode = false;
if (diff_data[i] == 255){
for (int yi=-size;yi<=size;yi++){
for (int xi=-size;xi<=size;xi++){
int px = (y+yi) * width + (x+xi);
if (diff_data[px] == 0){
erode = true;
break;
}
}
}
// break early if there's no erosion to be had
if (!erode){
return true;
}
}
}
}
return false;
}
}
* this code isnt actually working yet, for some reason. :) |