-
Notifications
You must be signed in to change notification settings - Fork 2
/
vpFindEye.cpp
109 lines (87 loc) · 2.8 KB
/
vpFindEye.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include "stdafx.h"
#include "vpProcess.h"
#include "vpPointDetector.h"
using namespace std;
using namespace cv;
CvHaarClassifierCascade* vpProcess::haarLeft = NULL;
CvHaarClassifierCascade* vpProcess::haarRight = NULL;
CvHaarClassifierCascade* vpProcess::haarBoth = NULL;
CvMemStorage* vpProcess::storage = NULL;
bool vpProcess::findEyes(int index)
{
Mat& img = this->subImgOut[index];
CvSeq* eyesL = cvHaarDetectObjects(&(CvMat)img, haarLeft, storage, 1.2, 4, 0, cvSize(2*VP_EYEMIN,VP_EYEMIN));
CvSeq* eyesR = cvHaarDetectObjects(&(CvMat)img, haarRight, storage, 1.2, 4, 0, cvSize(2*VP_EYEMIN,VP_EYEMIN));
Rect r;
// first, find the rectangle of one classifier with largest min/max range
double maxRange = 0;
Rect maxLeft = Rect(0,0,0,0);
Point2i ptLeft = Point2i(-1, -1);
for(int i = 0; i < (eyesL ? eyesL->total : 0); i++ )
{
r = Rect(*(CvRect*)cvGetSeqElem( eyesL, i ));
Mat subimg = img(r);
double mn, mx;
Point pt;
cv::minMaxLoc(subimg, &mn, &mx, 0, &pt);
if (fabs(mx-mn) > maxRange)
{
maxRange = fabs(mx-mn);
maxLeft = r;
ptLeft = pt;
}
}
maxRange = 0;
Rect maxRight = Rect(0,0,0,0);
Point2i ptRight = Point2i(-1, -1);
// now do the same for the other eye, with the added provision of non-intersection
for(int i = 0; i < (eyesR ? eyesR->total : 0); i++ )
{
r = Rect(*(CvRect*)cvGetSeqElem( eyesR, i ));
Rect rInt = r & maxLeft;
// skip if overlapping
if (rInt.area() != 0)
continue;
double mn, mx;
Mat subimg = img(r);
Point pt;
cv::minMaxLoc(subimg, &mn, &mx, 0, &pt);
if (fabs(mx-mn) > maxRange)
{
maxRange = fabs(mx-mn);
maxRight = r;
ptRight = pt;
}
}
// now make sure, since we are operating on the shrunken images, to scale everything back up to full-size
Point eyeL = VP_MAIN_DBG_SCL*(maxLeft.tl()+ptLeft);
Point eyeR = VP_MAIN_DBG_SCL*(maxRight.tl()+ptRight);
if (maxLeft.x > maxRight.x)
{
this->eyes2[index][0].setCenter(eyeL);
this->eyes2[index][1].setCenter(eyeR);
}
else
{
this->eyes2[index][0].setCenter(eyeR);
this->eyes2[index][1].setCenter(eyeL);
}
cvClearMemStorage(storage);
// check whether both were correctly detected
this->eyesFound[index] = (ptLeft.x >=0 && ptRight.x >= 0);
return this->eyesFound[index];
}
// sanity check for relative eye positions, discard if head is interpreted as way too tilted
bool vpProcess::checkEyes()
{
for (int i=0; i<2; i++)
{
Point2f pt = this->eyes2[i][1].center - this->eyes2[i][0].center;
// check tilt using tangent
this->eyesFound[i] &= (fabs(pt.y/pt.x) < VP_EYEMAXROT);
// not too close to edge also. causes problems later on
for (int j=0; j<2; j++)
this->eyesFound[i] &= Rect(VP_SUBSIZE, VP_SUBSIZE, camImageSize.width-2*VP_SUBSIZE, camImageSize.height-2*VP_SUBSIZE).contains(this->eyes2[i][j].center);
}
return (this->eyesFound[0] && this->eyesFound[1]);
}