To get gesture information, you might ask the "raspivid" command to output motion vectors from the video encoding process (there are other possibilities too). If you pick that route, you can do that with the -x command line option.
The output will be one motion vector per each 16 x 16 pixel macroblock. I have found the following handy (but I cannot guarantee the correctness of any code below) to describe the data block that gets output for each video frame (sample case: 320 x 320 pixels, snippet from Java code):
Code: Select all
int W = 320;
int H = 320;
int MB_SIZE = 16;
int MB_COLS = W / MB_SIZE;
int MB_ROWS = H / MB_SIZE;
int MB_COUNT = ((MB_COLS * MB_ROWS) + MB_COLS);
int VECSIZE = (MB_COUNT * 4);
Then, your program would have to read the output stream of "raspivid" and analyze the vectors... and decide if the criteria for a gesture command have been met.
In this step, you would find that simple gestures are easy to detect (e.g. "is the average of all vectors strongly biased to the left"), but that more complicated patterns are very hard to catch. :)
A snippet from my Java code to decode the vectors from a byte array... maybe useful, maybe not:
Code: Select all
import java.awt.Point;
public class MotionVector {
public Point center;
public Point dir;
public MotionVector(int centerX, int centerY, int dirX, int dirY) {
center = new Point(centerX, centerY);
dir = new Point(dirX, dirY);
}
}
ArrayList<MotionVector> vectors = new ArrayList<MotionVector>();
private void getVectors(byte[] v) {
// Prepare array for consumption
ByteBuffer bb = ByteBuffer.wrap(v);
int mby = 0;
int mbx = 0;
vectors.clear();
for (int i = 0; i < MB_COUNT; i++) {
byte x = bb.get();
byte y = bb.get();
// SAD is generally useless for motion analysis, but read the bytes anyway.
byte sadLo = bb.get();
byte sadHi = bb.get();
int sad = ((int) sadHi << 8) | ((int) sadLo & 0xFF);
int centerX = mbx * VideoGrabber.MB_SIZE;
int centerY = mby * VideoGrabber.MB_SIZE;
vectors.add(new MotionVector(centerX, centerY, x, y));
// Row and column incrementer.
mbx++;
if (mbx > MB_COLS) {
mbx = 0;
mby++;
}
}
}