論文下載地址:
http://www.cs./techreports/pdf/2005-012-blink-detection.pdf
程序介紹:
This system is the enhancement of my previous Eye Tracking system, where this system automatically locate the user's eye by detecting eye blinks. Motion analysis techniques are used in this stage, followed by online creation of the open eye template. The open eye template is used to locate the user's eye in the subsequent frames with template matching. Blink detection is performed using motion analysis techniques.
Since the operation requires extensive amount of computation, the search region is restricted in a small search window around the user's eye. This method will drastically reduces the computation needed thus making the system running smoothly in real time.
Author: Nashruddin Amin <me@> License: GPL Website: http://
See the complete tutorial at: http:///Real_Time_Eye_Tracking_and_Blink_Detection
Requirement ===========
This package requires the OpenCV library, freely available at: http:///projects/opencvlibrary
Compiling =========
Compile as usual. See the OpenCV wiki (http://opencv.) for info on how to use various IDE with OpenCV.
Usage ===== 1. Run the program. 2. Blink your eyes. You will see 2 rectangles. The green rectangle labels the object being tracked (your eye) and the red rectangle is the search window. 3. Move your head to see the eye tracking. 4. If you blink, the program will display the text 'blink!' in the window. 5. Press 'r' to repeat eye detection. 6. Press 'q' to quit.
Contact the author ================== Feel free to contact me@.
源程序:
-
-
-
-
-
-
-
-
-
-
- #include <stdio.h>
- #include "cv.h"
- #include "highgui.h"
- #define FRAME_WIDTH 240
- #define FRAME_HEIGHT 180
- #define TPL_WIDTH 16
- #define TPL_HEIGHT 12
- #define WIN_WIDTH TPL_WIDTH * 2
- #define WIN_HEIGHT TPL_HEIGHT * 2
- #define TM_THRESHOLD 0.4
- #define STAGE_INIT 1
- #define STAGE_TRACKING 2
- #define POINT_TL(r) cvPoint(r.x, r.y)
- #define POINT_BR(r) cvPoint(r.x + r.width, r.y + r.height)
- #define POINTS(r) POINT_TL(r), POINT_BR(r)
- #define DRAW_RECTS(f, d, rw, ro) /
- { /
- cvRectangle(f, POINTS(rw), CV_RGB(255, 0, 0), 1, 8, 0); /
- cvRectangle(f, POINTS(ro), CV_RGB(0, 255, 0), 1, 8, 0); /
- cvRectangle(d, POINTS(rw), cvScalarAll(255), 1, 8, 0); /
- cvRectangle(d, POINTS(ro), cvScalarAll(255), 1, 8, 0); /
- }
- #define DRAW_TEXT(f, t, d, use_bg) /
- if (d) /
- { /
- CvSize _size; /
- cvGetTextSize(t, &font, &_size, NULL); /
- if (use_bg) /
- { /
- cvRectangle(f, cvPoint(0, f->height), /
- cvPoint(_size.width + 5, /
- f->height - _size.height * 2), /
- CV_RGB(255, 0, 0), CV_FILLED, 8, 0); /
- } /
- cvPutText(f, t, cvPoint(2, f->height - _size.height / 2), /
- &font, CV_RGB(255,255,0)); /
- d--; /
- }
- CvCapture* capture;
- IplImage* frame, * gray, * prev, * diff, * tpl;
- CvMemStorage* storage;
- IplConvKernel* kernel;
- CvFont font;
- char* wnd_name = "video";
- char* wnd_debug = "diff";
- int get_connected_components(IplImage* img, IplImage* prev, CvRect window, CvSeq** comp);
- int is_eye_pair(CvSeq* comp, int num, CvRect* eye);
- int locate_eye(IplImage* img, IplImage* tpl, CvRect* window, CvRect* eye);
- int is_blink(CvSeq* comp, int num, CvRect window, CvRect eye);
- void delay_frames(int nframes);
- void init();
- void exit_nicely(char* msg);
- int
- main(int argc, char** argv)
- {
- CvSeq* comp = 0;
- CvRect window, eye;
- int key, nc, found;
- int text_delay, stage = STAGE_INIT;
- init();
- while (key != 'q')
- {
- frame = cvQueryFrame(capture);
- if (!frame)
- exit_nicely("cannot query frame!");
- frame->origin = 0;
- if (stage == STAGE_INIT)
- window = cvRect(0, 0, frame->width, frame->height);
- cvCvtColor(frame, gray, CV_BGR2GRAY);
- nc = get_connected_components(gray, prev, window, &comp);
- if (stage == STAGE_INIT && is_eye_pair(comp, nc, &eye))
- {
- delay_frames(5);
- cvSetImageROI(gray, eye);
- cvCopy(gray, tpl, NULL);
- cvResetImageROI(gray);
- stage = STAGE_TRACKING;
- text_delay = 10;
- }
- if (stage == STAGE_TRACKING)
- {
- found = locate_eye(gray, tpl, &window, &eye);
- if (!found || key == 'r')
- stage = STAGE_INIT;
- if (is_blink(comp, nc, window, eye))
- text_delay = 10;
- DRAW_RECTS(frame, diff, window, eye);
- DRAW_TEXT(frame, "blink!", text_delay, 1);
- }
- cvShowImage(wnd_name, frame);
- cvShowImage(wnd_debug, diff);
- prev = cvClone(gray);
- key = cvWaitKey(15);
- }
- exit_nicely(NULL);
- }
-
-
-
-
-
-
-
-
-
- int
- get_connected_components(IplImage* img, IplImage* prev, CvRect window, CvSeq** comp)
- {
- IplImage* _diff;
- cvZero(diff);
-
- cvSetImageROI(img, window);
- cvSetImageROI(prev, window);
- cvSetImageROI(diff, window);
-
- cvSub(img, prev, diff, NULL);
- cvThreshold(diff, diff, 5, 255, CV_THRESH_BINARY);
- cvMorphologyEx(diff, diff, NULL, kernel, CV_MOP_OPEN, 1);
-
- cvResetImageROI(img);
- cvResetImageROI(prev);
- cvResetImageROI(diff);
- _diff = cvClone(diff);
-
- int nc = cvFindContours(_diff, storage, comp, sizeof(CvContour),
- CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));
- cvClearMemStorage(storage);
- cvReleaseImage(&_diff);
- return nc;
- }
-
-
-
-
-
-
-
-
-
-
- int
- is_eye_pair(CvSeq* comp, int num, CvRect* eye)
- {
- if (comp == 0 || num != 2)
- return 0;
- CvRect r1 = cvBoundingRect(comp, 1);
- comp = comp->h_next;
- if (comp == 0)
- return 0;
- CvRect r2 = cvBoundingRect(comp, 1);
-
- if (abs(r1.width - r2.width) >= 5)
- return 0;
-
- if (abs(r1.height - r2.height) >= 5)
- return 0;
-
- if (abs(r1.y - r2.y) >= 5)
- return 0;
-
- int dist_ratio = abs(r1.x - r2.x) / r1.width;
- if (dist_ratio < 2 || dist_ratio > 5)
- return 0;
-
- CvPoint point = cvPoint(
- r1.x + (r1.width / 2),
- r1.y + (r1.height / 2)
- );
-
- *eye = cvRect(
- point.x - (TPL_WIDTH / 2),
- point.y - (TPL_HEIGHT / 2),
- TPL_WIDTH,
- TPL_HEIGHT
- );
- return 1;
- }
-
-
-
-
-
-
-
-
-
-
-
- int
- locate_eye(IplImage* img, IplImage* tpl, CvRect* window, CvRect* eye)
- {
- IplImage* tm;
- CvRect win;
- CvPoint minloc, maxloc, point;
- double minval, maxval;
- int w, h;
-
- point = cvPoint(
- (*eye).x + (*eye).width / 2,
- (*eye).y + (*eye).height / 2
- );
-
-
-
- win = cvRect(
- point.x - WIN_WIDTH / 2,
- point.y - WIN_HEIGHT / 2,
- WIN_WIDTH,
- WIN_HEIGHT
- );
-
- if (win.x < 0)
- win.x = 0;
- if (win.y < 0)
- win.y = 0;
- if (win.x + win.width > img->width)
- win.x = img->width - win.width;
- if (win.y + win.height > img->height)
- win.y = img->height - win.height;
-
-
-
- w = win.width - tpl->width + 1;
- h = win.height - tpl->height + 1;
- tm = cvCreateImage(cvSize(w, h), IPL_DEPTH_32F, 1);
-
- cvSetImageROI(img, win);
-
- cvMatchTemplate(img, tpl, tm, CV_TM_SQDIFF_NORMED);
- cvMinMaxLoc(tm, &minval, &maxval, &minloc, &maxloc, 0);
-
- cvResetImageROI(img);
- cvReleaseImage(&tm);
-
- if (minval > TM_THRESHOLD)
- return 0;
-
- *window = win;
-
- *eye = cvRect(
- win.x + minloc.x,
- win.y + minloc.y,
- TPL_WIDTH,
- TPL_HEIGHT
- );
- return 1;
- }
- int
- is_blink(CvSeq* comp, int num, CvRect window, CvRect eye)
- {
- if (comp == 0 || num != 1)
- return 0;
- CvRect r1 = cvBoundingRect(comp, 1);
-
- if (r1.x < window.x)
- return 0;
- if (r1.y < window.y)
- return 0;
- if (r1.x + r1.width > window.x + window.width)
- return 0;
- if (r1.y + r1.height > window.y + window.height)
- return 0;
-
- CvPoint pt = cvPoint(
- eye.x + eye.width / 2,
- eye.y + eye.height / 2
- );
-
- if (pt.x <= r1.x || pt.x >= r1.x + r1.width)
- return 0;
- if (pt.y <= r1.y || pt.y >= r1.y + r1.height)
- return 0;
- return 1;
- }
-
-
-
-
-
-
- void
- delay_frames(int nframes)
- {
- int i;
- for (i = 0; i < nframes; i++)
- {
- frame = cvQueryFrame(capture);
- if (!frame)
- exit_nicely("cannot query frame");
- cvShowImage(wnd_name, frame);
- if (diff)
- cvShowImage(wnd_debug, diff);
- cvWaitKey(30);
- }
- }
-
-
-
- void
- init()
- {
- char* msg[] = { "Blink Detection 1.0",
- "Copyright (c) 2009",
- "http://",
- "Press 'q' to quit...",
- "Press 'r' to restart...",
- "Have fun!" };
- int delay, i;
- capture = cvCaptureFromCAM(0);
- if (!capture)
- exit_nicely("Cannot initialize camera!");
- cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, FRAME_WIDTH);
- cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, FRAME_HEIGHT);
- frame = cvQueryFrame(capture);
- if (!frame)
- exit_nicely("cannot query frame!");
- cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.4, 0.4, 0, 1, 8);
- cvNamedWindow(wnd_name, 1);
- for (delay = 20, i = 0; i < 6; i++, delay = 20)
- while (delay)
- {
- frame = cvQueryFrame(capture);
- if (!frame)
- exit_nicely("cannot query frame!");
- DRAW_TEXT(frame, msg[i], delay, 0);
- cvShowImage(wnd_name, frame);
- cvWaitKey(30);
- }
- storage = cvCreateMemStorage(0);
- if (!storage)
- exit_nicely("cannot allocate memory storage!");
- kernel = cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_CROSS, NULL);
- gray = cvCreateImage(cvGetSize(frame), 8, 1);
- prev = cvCreateImage(cvGetSize(frame), 8, 1);
- diff = cvCreateImage(cvGetSize(frame), 8, 1);
- tpl = cvCreateImage(cvSize(TPL_WIDTH, TPL_HEIGHT), 8, 1);
- if (!kernel || !gray || !prev || !diff || !tpl)
- exit_nicely("system error.");
- gray->origin = frame->origin;
- prev->origin = frame->origin;
- diff->origin = frame->origin;
- cvNamedWindow(wnd_debug, 1);
- }
-
-
-
-
-
-
- void
- exit_nicely(char* msg)
- {
- cvDestroyAllWindows();
- if (capture)
- cvReleaseCapture(&capture);
- if (gray)
- cvReleaseImage(&gray);
- if (prev)
- cvReleaseImage(&prev);
- if (diff)
- cvReleaseImage(&diff);
- if (tpl)
- cvReleaseImage(&tpl);
- if (storage)
- cvReleaseMemStorage(&storage);
- if (msg != NULL)
- {
- fprintf(stderr, msg);
- fprintf(stderr, "/n");
- exit(1);
- }
- exit(0);
- }
|