Image Difference with OpenCV
by Carson Reynolds
Connsynn and I are working on a system to track tears. As part of it, we built a very quick image difference program to track motion between frames (to find things like blinks). As there wasn’t a clear example of using cvAbsDiff (which is a bit better than cvSub) we thought it’d be good to post ours. The program, image-diff.cpp follows:
#include <cv.h> #include <highgui.h> int main ( int argc, char **argv ) { // use first camera attached to computer CvCapture *capture; capture = cvCaptureFromCAM( 0 ); assert( capture ); // image data structures IplImage *img1; IplImage *img2; IplImage *imggray1; IplImage *imggray2; IplImage *imggray3; // get the camera image size IplImage *imgsize; imgsize = cvQueryFrame( capture ); if( !imgsize ) return -1; // grayscale buffers imggray1 = cvCreateImage( cvGetSize( imgsize ), IPL_DEPTH_8U, 1); imggray2 = cvCreateImage( cvGetSize( imgsize ), IPL_DEPTH_8U, 1); imggray3 = cvCreateImage( cvGetSize( imgsize ), IPL_DEPTH_8U, 1); int key = 0; while ( key != 'q' ) { // load image one img1 = cvQueryFrame( capture ); // convert rgb to grayscale cvCvtColor( img1, imggray1, CV_RGB2GRAY ); // quit if user press 'q' and wait a bit between images key = cvWaitKey( 500 ); // load image two img2 = cvQueryFrame( capture ); // convert rgb to grayscale cvCvtColor( img2, imggray2, CV_RGB2GRAY ); // compute difference cvAbsDiff( imggray1, imggray2, imggray3 ); // display difference cvNamedWindow( "video", 1 ); cvShowImage( "video", imggray3 ); } // release camera and clean up resources when "q" is pressed cvReleaseCapture( &capture ); cvDestroyWindow( "video" ); return 0; }
Here is a Makefile which uses g++ and assumes you have OpenCV installed. For it to work properly, the file above needs to be saved as image-diff.cpp in the same directory as the Makefile. It was tested using OS X and Macports, but will probably also work on Ubuntu, Linux, or anything with g++, pkg-config and OpenCV.
NAME = image-diff CC = g++ CFLAGS = -Wall -g -O0 `pkg-config --cflags opencv` LIBS = `pkg-config --libs opencv` all: $(CC) $(CFLAGS) $(LIBS) $(NAME).cpp -o $(NAME)
UPDATE: 12/12/2011 added simplified Makefile, fixed image color conversion ordering bug
Thanks.
I receive following error when I run this program,
OpenCV Error: Bad argument (Unknown array type) in cvarrToMat, file /home/sumit/Downloads/OpenCV-2.2.0/modules/core/src/matrix.cpp, line 641
terminate called after throwing an instance of ‘cv::Exception’
what(): /home/sumit/Downloads/OpenCV-2.2.0/modules/core/src/matrix.cpp:641: error: (-5) Unknown array type in function cvarrToMat
Aborted (core dumped)
Hello Sumit,
There was an error in the previous program in the color conversion step. Would you try again with the current version and let me know if it works?
Yes it does works. Thanks. 🙂
does this work with windows xp?!
It’s very slow. I have a framerate of about 0.5 img/sec. Is it normal ? How can it be improved ?
Nevermind…
key = cvWaitKey( 5 );
i tried to do it by passin two images to find t diffrnc….actually i want to find the diffrcnc between the two images(taken from same camera with same settings,focussin at same place say road but at diffrnt time) by keeping one as parent image and hv to notify if thr is any diffence in between two…i’m new to opencv pls help….. this s hw i modif’d t code
#include
#include
int main ( int argc, char **argv )
{
IplImage *img1;
IplImage *img2;
IplImage *imggray1;
IplImage *imggray2;
IplImage *imggray3;
if(argc==3)
{
img1 = cvLoadImage( argv[1] );
img2 = cvLoadImage( argv[2] );
}
else {exit(0);}
IplImage *imgsize1,*imgsize2;
//imgsize1 = cvSize( cvGetSize(img1));
//imgsize2 = cvSize( img2 );
if( !(imgsize1 && imgsize2)) return -1;
imggray1 = cvCreateImage( cvGetSize( img1 ), IPL_DEPTH_8U, 1);
imggray2 = cvCreateImage( cvGetSize( img2 ), IPL_DEPTH_8U, 1);
imggray3 = cvCreateImage( cvGetSize( img1 ), IPL_DEPTH_8U, 1);
int key = 0,c;
while(key != ‘q’)
{
// convert rgb to grayscale
cvCvtColor( img1, imggray1, CV_RGB2GRAY );
// quit if user press ‘q’ and wait a bit between images
key = cvWaitKey( 500 );
// convert rgb to grayscale
cvCvtColor( img2, imggray2, CV_RGB2GRAY );
// compute difference
cvAbsDiff( imggray1, imggray2, imggray3 );
// display difference
cvNamedWindow( “image”, 1 );
cvShowImage( “image”, imggray3 );
if( c == 27 ) break;
}
// release camera and clean up resources when “q” is pressed
cvReleaseImage( &img1 );
cvReleaseImage( &img2 );
cvDestroyWindow( “image” );
return 0;
thanks for sharing the modification!
How to solve this exception
Assertion failed (src1.size() == dst.size() && src1.type() == dst. type())
i have tried this code and got this error.
Unhandled exception at 0x75b040f8 in prjct2.exe: Microsoft C++ exception: cv::Exception at memory location 0x0032aeb0..
how to solve this?
Getting this to compile on my Mac was not trivial but I did some searching and found a series of edits that got the makefile working:
—-BEGIN MAKEFILE—-
NAME = image-diff
CC = g++
CFLAGS = -Wall -g -O0
LIBS = `pkg-config –cflags opencv –libs`
all:
$(CC) $(NAME).cpp -o $(NAME) $(CFLAGS) $(LIBS)
—-END MAKEFILE—-
I had to instal pkg-config because I did not have it installed. I also noticed that the makefile posted above had the string `pkg-config –cflags opencv` twice so I deleted it from the CFLAGS line. And I reordered the last line so that $(LIBS) comes last.