#include "cv.h"
#include "highgui.h"
#include <stdlib.h>
#include<sapi.h>

// Global variables
CvHaarClassifierCascade* cascade = 0;
CvMemStorage* storage = 0;
CvHaarClassifierCascade* cascade_e=0;
CvMemStorage* storage1 = 0;
int close=0,blink=0,eye_closed=0;
int continuous_blink=0;
int no_of_frames=1;
double t;
int temp,fps;
int ms;
int flag=0,count=0;
// Alarm function
bool alarm(int flag)
{
int i=0;
ISpVoice * pVoice = NULL;

if (FAILED(::CoInitialize(NULL)))
return FALSE;

HRESULT hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void **)&pVoice);
while(i<1){
if( SUCCEEDED( hr ) )
{
if(flag==1)
hr = pVoice->Speak(L"wake up, you are Fifty percent drowsy", 0, NULL);
else
hr = pVoice->Speak(L"wake up, you are hundred percent drowsy", 0, NULL);
}
i++;
}
pVoice->Release();
pVoice = NULL;

::CoUninitialize();
return TRUE;

}
/*Eyes detection*/
void detectEyes( IplImage *img,CvRect *r)
{ int i;
int eye_detect=0;
CvSeq *eyes;

//eye detection starts
/* Set the Region of Interest: estimate the eyes' position */

cvSetImageROI(img, /* the source image */
cvRect
(
r->x, /* x = start from leftmost */
r->y + (r->height/5.5), /* y = a few pixels from the top */
r->width, /* width = same width with the face */
(r->height*1)/3.0 /* height = 1/3 of face height */
)
);

/* detect the eyes */
eyes = cvHaarDetectObjects( img, /* the source image, with the estimated location defined */
cascade_e, /* the eye classifier */
storage1, /* memory buffer */
1.15, 3, 0, /* tune for your app */
cvSize(25, 15) /* minimum detection scale */
);


//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
if(no_of_frames==120)
{
printf("total blink in a minute is =%d\n",blink);
no_of_frames=0;
blink=0;
continuous_blink=0;
count=0;
}

//eye closed
if(eyes->total==0 && flag<=1)
{
flag=1;
printf("flag= %d",flag);
}
//eye open include
if(eyes->total!=0 && flag==1)
{
flag=2;
printf("flag= %d",flag);
goto l1;
}
//eye open include
if(eyes->total!=0 && flag==2)
{
flag=3;
printf("flag= %d",flag);
goto l1;
}
//eye open set flag=0
if(eyes->total!=0 && flag==3)
{
flag=0;
printf("flag= %d",flag);
goto l1;
}
//eye closed include
if(eyes->total==0 && flag==2 || flag==3)
{
flag=4;
printf("flag= %d",flag);
goto l1;
}
//eye closed include
if(eyes->total==0 && flag==4)
{
flag=5;
printf("flag= %d",flag);
goto l1;
}
//eye closed set flag=1
if(eyes->total==0 && flag==5)
{
flag=1;
printf("flag= %d",flag);
goto l1;
}
//eye open include
if(eyes->total!=0 && flag==4 || flag==5)
{
flag=6;
printf("flag= %d",flag);
goto l1;
}

//eye open include
if(eyes->total!=0 && flag==6)
{
flag=7;
printf("flag= %d",flag);
goto l1;
}
//eye open set flag=0
if(eyes->total!=0 && flag==7)
{
flag=0;
printf("flag= %d",flag);
goto l1;
}
//eye close
l1:
if(eyes->total==0 && flag==6 || flag==7)
{
// printf("person is drowsy\n");
flag=1;
continuous_blink++;
printf("continuous_blink=%d\n",continuous_blink);
if(continuous_blink>=3)
{
alarm(1);
}

}
//blink count
if(eyes->total == 0)//close
{
if(close==0){
blink++;
}
close=1;
}
else{ //open
close=0;
eye_closed=0;
}
if(close==1){
eye_closed++;
//printf("\ Eyes total.- %d",eyes->total);
printf("\ Eyes closed in frame no.- %d",eye_closed);
if(eye_closed==4)
{
alarm(1);
}
if(eye_closed>=8)
alarm(2);

}
//printf("\no of blinks are %d",eye_closed);

//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
printf("\n No. of frame is %d",no_of_frames++);
cvNamedWindow( "Eye1", 1 );

/* draw a rectangle for each detected eye */
for( i = 0; i <(eyes ? eyes->total : 0); i++ )
{

/* get one eye */
CvRect *eye = (CvRect*)cvGetSeqElem(eyes, i);
/* draw a blue rectangle */
int x,y,width,height;
x=eye->x;
y=eye->y;
width=eye->width;
height=eye->height;

cvRectangle(img,
cvPoint(eye->x, eye->y),
cvPoint(eye->x + eye->width, eye->y + eye->height),
CV_RGB(0, 0, 255),
1, 8, 0
);
cvShowImage( "Eye1", img );

}
cvResetImageROI(img);





}


void detect_faces(IplImage* img)
{
int i=0;
IplImage* gray;
CvRect *r;

/* Convert multichannel to 1-channel for faster processing */
if (img->nChannels == 1)
{
gray = cvCloneImage(img);
}
else
{
gray = cvCreateImage(cvGetSize(img), img->depth, 1);
cvCvtColor(img, gray, CV_RGB2GRAY);
}

/* detect faces */
//t = (double)cvGetTickCount();

CvSeq* faces = cvHaarDetectObjects(
gray,
cascade,
storage,
1.1,
3,
CV_HAAR_DO_CANNY_PRUNING,
cvSize(20, 20)
);
// t = (double)cvGetTickCount() - t;
// ms = cvRound( t / ((double)cvGetTickFrequency() * 1000.0) );
//printf("Face Detection took %d ms \n", ms);

for( i = 0; i < (faces ? faces->total : 0); i++ )
{
/* Draw red boxes on the faces found */
r = (CvRect*)cvGetSeqElem(faces,i);

cvRectangle(
img,
cvPoint(r->x, r->y),
cvPoint(r->x + r->width, r->y + r->height),
CV_RGB(255, 0, 0),
1, 8, 0
);



detectEyes(img,r);

cvResetImageROI(img);
}
}

int main( int argc, char** argv )
{
IplImage *frame;
CvCapture *capture;
if (!cascade) {
char* file = "haarcascade_frontalface_alt_tree.xml";
cascade = (CvHaarClassifierCascade*) cvLoad(file, 0, 0, 0);
storage = cvCreateMemStorage(0);
}

if (!cascade_e) {
char* file = "haarcascade_eye_tree_eyeglasses.xml";
cascade_e = (CvHaarClassifierCascade*) cvLoad(file, 0, 0, 0);
storage1 = cvCreateMemStorage(0);
}


/* load the video AVI or WMV file */
capture = cvCaptureFromAVI( "indrajeet_FI-40_BI-15_DYes.wmv" );
fps = ( int )cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_COUNT );
printf("FPS=%d\n",fps);
// Gets the input video stream from camera
//capture = cvCaptureFromCAM( 0 );


// Checks if the input stream is obtained
if( !capture )
{
fprintf( stderr, "ERROR: capture is NULL \n" );
getchar();
return -1;
}

// Show the image captured from the camera in the window and repeat
while( 1 )
{

// Get one frame
for(int i=0;i<10;i++)
frame = cvQueryFrame( capture );

// Cecks if a frame is obtained
if( !frame )
{
fprintf( stderr, "END of the VIDEO..\n" );
getchar();
//break;
goto l2;
}

// Flips the frame into mirror image
cvFlip(frame,frame,1);

// Call the function to detect and draw the face portion

detect_faces(frame);

cvShowImage( "video", frame );

//If ESC key pressed exit
if( (cvWaitKey(10) & 255) == 27 )
break;
}

// Release the capture device housekeeping


/* always check */
l2:
cvReleaseCapture( &capture );
cvDestroyWindow( "video" );

return 0;
}