Question

I'm using frame differencing and opencv to detect movement between frames (absdiff, threshold, erode, etc).

How can I get the coordinates of the individual locations of the movements (the rect: x, y, width, height), basically of the white blobs?

Was it helpful?

Solution

I'm doing the same thing. Here's the code I have (some things handled in different classes, I just put it all together here). The first part is what you already have, skip down to the contours part.

/* This is the background subtraction you already have */
Mat tmp1;
GaussianBlur( frame, tmp1, Size(5,5),0,0); //Blurring one image is sufficient to eliminate noise
absdiff(tmp1, frameLast, tmp1);
cvtColor(tmp1,tmp1,CV_RGB2GRAY);
threshold( tmp1, tmp1, CV_THRESH_OTSU, 100, CV_THRESH_BINARY);
/*cleaning up */
int erosion_type = MORPH_RECT; // MORPH_RECT, MORPH_CROSS, MORPH_ELLIPSE
int erosion_size = 3;
Mat erosion_element = getStructuringElement( erosion_type, Size( 2*erosion_size + 1, 2*erosion_size+1), Point( erosion_size, erosion_size));

int dilation_type = MORPH_RECT;
int dilation_size = 5;
Mat dilation_element = getStructuringElement( dilation_type, Size( 2*dilation_size + 1, 2*dilation_size+1), Point( dilation_size, dilation_size));

erode(tmp1,tmp1,erosion_element);
dilate(tmp1,tmp1,dilation_element);

/* Here I am getting the contours */
vector<vector<Point> > contours;
findContours( tmp1, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );
int minArea = 100, maxArea = 1000; //keep only contours of a certain size
for (vector<vector<Point> >::iterator it=contours.end(); it!=contours.begin(); it--) {
    if ((*it).size()<minArea || (*it).size()>maxArea) {
        contours.erase(it);
    }
}

drawContours(displayer, contours, a, Scalar(122,200,222),2);

See here for more details (especially the options on which contours to find, can help you narrow down what you find. I just used CV_RETR_EXTERNAL).

Note that I made (before) a Mat displayer, which is a deep-copy of frame (copied with frame.copyTo(displayer). This is because if you draw stuff directly on frame, it'll be transferred to "frameLast" and pop up with the next absDiff. Of course you could avoid this extra image by cleanly copying frame to frameLast before drawing (so drawing everything at the end), I do this so I can easily draw from anywhere in the code, makes it easier for now since I'm trying a lot of things and want to be able to see intermediate steps at times.

OTHER TIPS

Basically, you may want to try cvBlobsLib. Currently using it. Of course at first it is very hard to deal with it. Later on when you get use to it, it is pretty simple to use. It find the white blobs in the image, vice versa. then you can use bounding box. from there you can get the point location.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top