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
*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;
}