Movement Detection Using OpenCV
I am starting to like the Open Computer Vision Library (OpenCV). I have done some image processing with it for my art class (link) and I really enjoyed it. But when I tried to make some web cam application I realised that OpenCV fails to detect my web camera. After about 2 days spent installing/uninstalling various Microsoft SDK’s I found out that the problem may be somewhere in Visual Studio, because the program crashes only when I start it with debugging, and it works like a charm on ctrl+F5 – no debugging. I couldn’t find solution for this for now.
However, I have still managed to create a sample movement detection application with OpenCV. And this is how it looks:
Ain’t computer science fun? ![]()
The algorithm
Well, the algorithm for movement detection here is pretty simple:
- Get two frames from webcam
- Blur the images to reduce camera noise
- Calculate absolute differences from them
- Make the new image with only those differences
- Convert step 4 image to grayscale
- Add binary threshold filter to leave only white and black pixels in grayscale image
- If there are more than 100 white pixels in area of a circle, then movement is detected!
Implementation
OpenCV provide us very good tools for doing transformations mentioned in algorithm.
Blurring is done with cvSmooth(); calculating absolute difference cvAbsDiff(); converting to grayscale – cvCvtColor(); threshold – cvThreshold();
A simple snippet to do first 6 steps of algorithm (extracted from the sourcecode at the bottom):
void frameProcessor::compareImages(IplImage * img1, IplImage * img2) //Compare two images (frame)
{
this->clear(); //Clears image buffers.
//Check if it's images
if ((img1 == 0) || (img2 == 0)) { fprintf(stderr, "One/both of images to compare are null\n"); return; }
//Clone image in order not to modify the original
this->img1 = cvCloneImage(img1);
this->img2 = cvCloneImage(img2);
//Create processed image buffer
this->processedImg = cvCreateImage(cvGetSize(this->img1), 8, 3);
//Blur images to get rid of camera noise
cvSmooth(this->img1, this->img1, CV_BLUR, 3);
cvSmooth(this->img2, this->img2, CV_BLUR, 3);
//Calc absolute difference
cvAbsDiff(this->img1, this->img2, this->processedImg);
//Create gray image buffer
this->processedImgGray = cvCreateImage(cvGetSize(this->processedImg), 8, 1);
//Convert colored image to grayscale
cvCvtColor(this->processedImg, this->processedImgGray, CV_RGB2GRAY);
//Perform binary treshold filter on image to leave only white and black pixels
cvThreshold(this->processedImgGray, this->processedImgGray, 30, 255, CV_THRESH_BINARY);
}
And the white color count in area is calculated by following function (also extracted from the source):
int frameProcessor::getWhiteInArea(int startX, int startY, int w, int h)
{
if (this->processedImgGray == 0) return -1; //If there's no grayscale processed image, return error.
//Go back to bounds
if (startX < 0) startX = 0;
if (startX >= this->processedImgGray->width) return -1;
if (startY < 0) startY = 0;
if (startY >= this->processedImgGray->height) return -1;
//Initialise counter
int whiteCount = 0;
//Loop through area
for (int x = startX; ((x <= startX+w) && (x < this->processedImgGray->width)); x++)
{
for (int y = startY; ((y <= startY+h) && (y < this->processedImgGray->height)); y++)
{
int tmp = ((uchar*)(this->processedImgGray->imageData + this->processedImgGray->widthStep*y))[x];
if (tmp == 255) whiteCount++; //If it's white -> add to whitecount.
}
}
return whiteCount;
}
And that is everything you need for motion detecting with OpenCV. Now you only check if there are more than, let’s say 100 pixels in area and say that the movement was detected here.
The Sourcecode
The application source is available to download here. The additional dependencies for the project are cv.lib highgui.lib cxcore.lib.
Feel free to comment, edit it, etc.
ryan Says:
Hi
would this method work even if the camera is also moving. ?
Posted on November 5th, 2009 at 20:21
Saulius Says:
No, I think it will not
Posted on November 5th, 2009 at 20:53
Sharath Says:
Hi,
Using your first function, can i compare two images?
I have an image (JPG) stored in my application and I take a picture using my camera and want to compare and see how similar they are.
Do I need to take care that both images are of equal dimension?
Please do let me know if u can help.
Thanks.
Posted on January 11th, 2010 at 11:04
ekez Says:
using opencv, can opencv determine if it is a male of a female?its only for our thesis
Posted on January 18th, 2010 at 08:00
mye Says:
hey, got a question about white area count.
i am processing a binary video and would like to count only the white area. how should i do this?
i dont really understand your code, the part with ‘this’. what is ‘this’ actually?
thanks in advance for your help!
Posted on January 18th, 2010 at 09:49
Armando Says:
Hey, nice work
I’m experimenting with this kind of things too. But old blog it seems I’m late…
Posted on February 17th, 2010 at 23:47