Here is a simple AR demo for beginners (-includes me). The program augments only in 2D with a picture or a clip.
The video plays rather slow, due to 'cvWaitkey' and Opencv fetching frames from avi. I have included a faster version of the 'Big Buck bunny' with the source
Files:
Download from DsynFLO box folder - https://app.box.com/s/j0522pl71rzkacofivws
Links:
http://www.bigbuckbunny.org/
If you want to download only the (modified) video used in this demo, try the link below-
640x480, Xvid/LameMP3
Pattern (Size A4,JPEG):
Videos:
Source Code:
The video plays rather slow, due to 'cvWaitkey' and Opencv fetching frames from avi. I have included a faster version of the 'Big Buck bunny' with the source
Files:
Download from DsynFLO box folder - https://app.box.com/s/j0522pl71rzkacofivws
*Important Updates:
Checkout full Source for Marker based augmented reality here :
openAR-
Checkout updated code for openCV 2.4.9 here : simplar2-
Links:
http://www.bigbuckbunny.org/
If you want to download only the (modified) video used in this demo, try the link below-
640x480, Xvid/LameMP3
Pattern (Size A4,JPEG):
Videos:
Source Code:
//______________________________________________________________________________________ // OpenCV Simple Augmented Reality Program // Author: Bharath Prabhuswamy //______________________________________________________________________________________ //______________________________________________________________________________________ #include <stdio.h> #include <stdlib.h> #include "cv.h" #include "highgui.h" int main() { CvCapture *capture = 0; IplImage *image = 0; IplImage *frame = 0; IplImage *disp,*neg_img,*cpy_img; int key = 0; int fcount = 0; int option = 0; capture = cvCaptureFromCAM( 0 ); if ( !capture ) return -1; //Use a video with aspect ratio 4:3 CvCapture* vid = cvCreateFileCapture("trailer.avi"); if ( !vid ) return -1; IplImage *pic = cvLoadImage("pic.jpg"); cvFlip(pic,pic,1); int b_width = 5; int b_height = 4; int b_squares = 20; CvSize b_size = cvSize( b_width, b_height ); //The pattern actually has 6 x 5 squares, but has 5 x 4 = 20 'ENCLOSED' corners CvMat* warp_matrix = cvCreateMat(3,3,CV_32FC1); CvPoint2D32f* corners = new CvPoint2D32f[ b_squares ]; int corner_count; printf("Select an option to run the program\n\n"); printf("1. Show an Image over the pattern.\n"); printf("2. Play a Clip over the pattern.\n"); printf("3. Mark the pattern.\n\n"); scanf("%d",&option); //Quit on invalid entry if(!(option>=1 && option<=3)) { printf("Invalid selection."); return -1; } cvNamedWindow("Video",CV_WINDOW_AUTOSIZE); while(key!='q') { image = cvQueryFrame( capture ); if( !image ) break; cvFlip(image,image,1); disp = cvCreateImage( cvGetSize(image), 8, 3 ); cpy_img = cvCreateImage( cvGetSize(image), 8, 3 ); neg_img = cvCreateImage( cvGetSize(image), 8, 3 ); IplImage* gray = cvCreateImage( cvGetSize(image), image->depth, 1); int found = cvFindChessboardCorners(image, b_size, corners, &corner_count, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS); cvCvtColor(image, gray, CV_BGR2GRAY); //This function identifies the pattern from the gray image, saves the valid group of corners cvFindCornerSubPix(gray, corners, corner_count, cvSize(11,11),cvSize(-1,-1), cvTermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 )); if( corner_count == b_squares ) { if(option == 1) { CvPoint2D32f p[4]; CvPoint2D32f q[4]; IplImage* blank = cvCreateImage( cvGetSize(pic), 8, 3); cvZero(blank); cvNot(blank,blank); //Set of source points to calculate Perspective matrix q[0].x= (float) pic->width * 0; q[0].y= (float) pic->height * 0; q[1].x= (float) pic->width; q[1].y= (float) pic->height * 0; q[2].x= (float) pic->width; q[2].y= (float) pic->height; q[3].x= (float) pic->width * 0; q[3].y= (float) pic->height; //Set of destination points to calculate Perspective matrix p[0].x= corners[0].x; p[0].y= corners[0].y; p[1].x= corners[4].x; p[1].y= corners[4].y; p[2].x= corners[19].x; p[2].y= corners[19].y; p[3].x= corners[15].x; p[3].y= corners[15].y; //Calculate Perspective matrix cvGetPerspectiveTransform(q,p,warp_matrix); //Boolean juggle to obtain 2D-Augmentation cvZero(neg_img); cvZero(cpy_img); cvWarpPerspective( pic, neg_img, warp_matrix); cvWarpPerspective( blank, cpy_img, warp_matrix); cvNot(cpy_img,cpy_img); cvAnd(cpy_img,image,cpy_img); cvOr(cpy_img,neg_img,image); cvShowImage( "Video", image); } else if(option == 2) { CvPoint2D32f p[4]; CvPoint2D32f q[4]; frame = cvQueryFrame(vid); if (!frame) printf("error frame"); IplImage* blank = cvCreateImage( cvGetSize(frame), 8, 3); cvZero(blank); cvNot(blank,blank); q[0].x= (float) frame->width * 0; q[0].y= (float) frame->height * 0; q[1].x= (float) frame->width; q[1].y= (float) frame->height * 0; q[2].x= (float) frame->width; q[2].y= (float) frame->height; q[3].x= (float) frame->width * 0; q[3].y= (float) frame->height; p[0].x= corners[0].x; p[0].y= corners[0].y; p[1].x= corners[4].x; p[1].y= corners[4].y; p[2].x= corners[19].x; p[2].y= corners[19].y; p[3].x= corners[15].x; p[3].y= corners[15].y; cvGetPerspectiveTransform(q,p,warp_matrix); //Boolean juggle to obtain 2D-Augmentation cvZero(neg_img); cvZero(cpy_img); cvWarpPerspective( frame, neg_img, warp_matrix); cvWarpPerspective( blank, cpy_img, warp_matrix); cvNot(cpy_img,cpy_img); cvAnd(cpy_img,image,cpy_img); cvOr(cpy_img,neg_img,image); cvShowImage( "Video", image); } else { CvPoint p[4]; p[0].x=(int)corners[0].x; p[0].y=(int)corners[0].y; p[1].x=(int)corners[4].x; p[1].y=(int)corners[4].y; p[2].x=(int)corners[19].x; p[2].y=(int)corners[19].y; p[3].x=(int)corners[15].x; p[3].y=(int)corners[15].y; cvLine( image, p[0], p[1], CV_RGB(255,0,0),2); cvLine( image, p[1], p[2], CV_RGB(0,255,0),2); cvLine( image, p[2], p[3], CV_RGB(0,0,255),2); cvLine( image, p[3], p[0], CV_RGB(255,255,0),2); //or simply //cvDrawChessboardCorners(image, b_size, corners, corner_count, found); cvShowImage( "Video", image); } } else { //Show gray image when pattern is not detected cvFlip(gray,gray); cvShowImage( "Video", gray ); } key = cvWaitKey(1); } cvDestroyWindow( "Video" ); cvReleaseCapture( &vid ); cvReleaseMat(&warp_matrix); cvReleaseCapture( &capture ); return 0; }
Hi! I haven't tried running this, but what will happen if I tilt the pattern towards or away from the camera (about an axis parallel to the cam)?
ReplyDeleteAs long as the pattern is visible, the picture gets augmented (up to certain acute angle and distance).
ReplyDeleteOk.. great!
ReplyDeletegreat sample.... thanks 4 sharing..... :)
ReplyDeleteWhile the sample works, the coding is horrible.
ReplyDeleteIn your example you have multiple memory leaks - when you create images using cvCreateImage, images are never released. Compiler will not automatically free this memory for you, so the application will run out of memory and crash. This isn't java or python, if you want memory to be automatically released, use smart pointers.
@segfault: True, here's an article that might help - http://www.aishack.in/2010/01/opencv-memory-management
ReplyDelete@segfault: I agree that this code is Horrible.
ReplyDeleteI quote what I said before..."These programs are just guidelines of the algorithms that help you achieve the objective of the program."
..And its up to you to go ahead and show all the programming skills, having done this.
hi bharath is there any sample with 3d animation with c# & open cv
ReplyDeletehi,
ReplyDeleteI'm wondering if it would be possible to track multiple markers using opencv? This is a very cool sample by the way!
@tanarama:
ReplyDeleteI ve not heard of any 3D animation using opencv, i would suggest combining opengl to get 3d objects in to the frame.
@Eamonn:
Thanks..:)..
Yes it is possible to have multiple marker tracking system. The above program and any other program for that matter which uses the function
cvFindChessboardCorners detects only one pattern. if two such patterns are shown it would be confused and throw an error.
The only way to detect more than one pattern is to have a custom pattern detecting algorithm.
thanks for the info, do you have any helpful links where I could start to do this?
ReplyDeleteIts a good idea to have a copy of Opencv O'reilly book.
ReplyDeletehttp://oreilly.com/catalog/9780596516130
You can look into ARToolkit, an open source lib. for augmented reality. It can track multiple markers and augment it.
http://www.hitl.washington.edu/artoolkit/documentation/
Is there a way to do multiple marker tracking? thanks
ReplyDeleteHi Bharath,
ReplyDeletethank you for the wonderful example.
But I am having trouble compiling the source file, I am getting this error:
error LNK2019: unresolved external symbol _cvFindChessboardCorners referenced in function _main
I have included almost all files, which header file I might be missing?
Thanks the program is working perfectly (QT 4.7 and OpenCV 2.1), just would be better if you use some "if" when the pointer to images and videos is empty.
ReplyDeleteBye!
Hey awesome work buddy..similarly is it possible to overlay 3d models on to the pattern ..if yes then pls do share
ReplyDeleteGr8! Works out of the box - Used it on Ubuntu !
ReplyDeleteThanks a lot, it worked very well
ReplyDeleteI was trying to find a simple marker tracker in opencv !!!
Roger
hello.
ReplyDeletenice post..
i want to implement same with android..can u please guide for the same.