-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
255 lines (217 loc) · 8.24 KB
/
main.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
#include <queue>
#include <stdio.h>
#include <math.h>
#include "constants.h"
#include "findEyeCenter.h"
#include "findEyeCorner.h"
#include "DCMotor.h"
#include "Image_Process.h"
using namespace std;
using namespace cv;
/** Constants **/
/** Function Headers */
void detectAndDisplay( cv::Mat frame );
/** Global variables */
//-- Note, either copy these two files from opencv/data/haarscascades to your current folder, or change these locations
cv::String face_cascade_name = "/home/pi/opencv-2.4.13/data/haarcascades/haarcascade_frontalface_alt.xml";
cv::CascadeClassifier face_cascade;
std::string main_window_name = "Capture - Face detection";
std::string face_window_name = "Capture - Face";
cv::RNG rng(12345);
cv::Mat debugImage;
cv::Mat skinCrCbHist = cv::Mat::zeros(cv::Size(256, 256), CV_8UC1);
/**
* @function main
*/
int main( int argc, const char** argv ) {
Motor_init();
cv::Mat frame;
// Load the cascades
if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade, please change face_cascade_name in source code.\n"); return -1; };
cv::namedWindow(main_window_name, CV_WINDOW_AUTOSIZE);
cv::moveWindow(main_window_name, 400, 100);
cv::namedWindow(face_window_name, CV_WINDOW_NORMAL);
cv::moveWindow(face_window_name, 10, 100);
cv::namedWindow("Right Eye",CV_WINDOW_NORMAL);
cv::moveWindow("Right Eye", 10, 600);
cv::namedWindow("Left Eye",CV_WINDOW_NORMAL);
cv::moveWindow("Left Eye", 10, 800);
createCornerKernels();
ellipse(skinCrCbHist, cv::Point(113, 155.6), cv::Size(23.4, 15.2),
43.0, 0.0, 360.0, cv::Scalar(255, 255, 255), -1);
// I make an attempt at supporting both 2.x and 3.x OpenCV
#if CV_MAJOR_VERSION < 3
CvCapture* capture = cvCaptureFromCAM( -1 );
if( capture ) {
while( true ) {
frame = cvQueryFrame( capture );
#else
cv::VideoCapture capture(-1);
if( capture.isOpened() ) {
while( true ) {
capture.read(frame);
#endif
// mirror it
cv::flip(frame, frame, 1);
frame.copyTo(debugImage);
// Apply the classifier to the frame
if( !frame.empty() ) {
detectAndDisplay( frame );
}
else {
printf(" --(!) No captured frame -- Break!");
break;
}
imshow(main_window_name,debugImage);
int c = cv::waitKey(10);
if( (char)c == 'c' ) { break; }
if( (char)c == 'f' ) {
//imwrite("frame.png",frame);
}
}
}
releaseCornerKernels();
return 0;
}
void findEyes(cv::Mat frame_gray, cv::Rect face) {
cv::Mat faceROI = frame_gray(face);
cv::Mat debugFace = faceROI;
if (kSmoothFaceImage) {
double sigma = kSmoothFaceFactor * face.width;
GaussianBlur( faceROI, faceROI, cv::Size( 0, 0 ), sigma);
}
//-- Find eye regions and draw them
int eye_region_width = face.width * (kEyePercentWidth/100.0);
int eye_region_height = face.width * (kEyePercentHeight/100.0);
int eye_region_top = face.height * (kEyePercentTop/100.0);
cv::Rect leftEyeRegion(face.width*(kEyePercentSide/100.0),
eye_region_top,eye_region_width,eye_region_height);
cv::Rect rightEyeRegion(face.width - eye_region_width - face.width*(kEyePercentSide/100.0),
eye_region_top,eye_region_width,eye_region_height);
//-- Find Eye Centers
cv::Point leftPupil = findEyeCenter(faceROI,leftEyeRegion,"Left Eye");
cv::Point rightPupil = findEyeCenter(faceROI,rightEyeRegion,"Right Eye");
Point full_left = findEyeCenter(frame_gray, leftEyeRegion, "full_left");
Point full_right = findEyeCenter(frame_gray, rightEyeRegion, "full_right");
printf("right : %i, %i\n", full_right.x, full_right.y);
printf("left : %i, %i\n", full_left.x, full_left.y);
// get corner regions
cv::Rect leftRightCornerRegion(leftEyeRegion);
leftRightCornerRegion.width -= leftPupil.x;
leftRightCornerRegion.x += leftPupil.x;
leftRightCornerRegion.height /= 2;
leftRightCornerRegion.y += leftRightCornerRegion.height / 2;
cv::Rect leftLeftCornerRegion(leftEyeRegion);
leftLeftCornerRegion.width = leftPupil.x;
leftLeftCornerRegion.height /= 2;
leftLeftCornerRegion.y += leftLeftCornerRegion.height / 2;
cv::Rect rightLeftCornerRegion(rightEyeRegion);
rightLeftCornerRegion.width = rightPupil.x;
rightLeftCornerRegion.height /= 2;
rightLeftCornerRegion.y += rightLeftCornerRegion.height / 2;
cv::Rect rightRightCornerRegion(rightEyeRegion);
rightRightCornerRegion.width -= rightPupil.x;
rightRightCornerRegion.x += rightPupil.x;
rightRightCornerRegion.height /= 2;
rightRightCornerRegion.y += rightRightCornerRegion.height / 2;
rectangle(debugFace,leftRightCornerRegion,200);
rectangle(debugFace,leftLeftCornerRegion,200);
rectangle(debugFace,rightLeftCornerRegion,200);
rectangle(debugFace,rightRightCornerRegion,200);
// change eye centers to face coordinates
rightPupil.x += rightEyeRegion.x;
rightPupil.y += rightEyeRegion.y;
leftPupil.x += leftEyeRegion.x;
leftPupil.y += leftEyeRegion.y;
//printf("right : %i, %i\n", rightPupil.x,rightPupil.y);
//printf("left : %i, %i\n", leftPupil.x, leftPupil.y);
// draw eye centers
circle(debugFace, rightPupil, 3, 1234);
circle(debugFace, leftPupil, 3, 1234);
//-- Find Eye Corners
if (kEnableEyeCorner) {
cv::Point2f leftRightCorner = findEyeCorner(faceROI(leftRightCornerRegion), true, false);
leftRightCorner.x += leftRightCornerRegion.x;
leftRightCorner.y += leftRightCornerRegion.y;
cv::Point2f leftLeftCorner = findEyeCorner(faceROI(leftLeftCornerRegion), true, true);
leftLeftCorner.x += leftLeftCornerRegion.x;
leftLeftCorner.y += leftLeftCornerRegion.y;
cv::Point2f rightLeftCorner = findEyeCorner(faceROI(rightLeftCornerRegion), false, true);
rightLeftCorner.x += rightLeftCornerRegion.x;
rightLeftCorner.y += rightLeftCornerRegion.y;
cv::Point2f rightRightCorner = findEyeCorner(faceROI(rightRightCornerRegion), false, false);
rightRightCorner.x += rightRightCornerRegion.x;
rightRightCorner.y += rightRightCornerRegion.y;
circle(faceROI, leftRightCorner, 3, 200);
circle(faceROI, leftLeftCorner, 3, 200);
circle(faceROI, rightLeftCorner, 3, 200);
circle(faceROI, rightRightCorner, 3, 200);
}
imshow(face_window_name, faceROI);
// cv::Rect roi( cv::Point( 0, 0 ), faceROI.size());
// cv::Mat destinationROI = debugImage( roi );
// faceROI.copyTo( destinationROI );
}
cv::Mat findSkin (cv::Mat &frame) {
cv::Mat input;
cv::Mat output = cv::Mat(frame.rows,frame.cols, CV_8U);
cvtColor(frame, input, CV_BGR2YCrCb);
for (int y = 0; y < input.rows; ++y) {
const cv::Vec3b *Mr = input.ptr<cv::Vec3b>(y);
// uchar *Or = output.ptr<uchar>(y);
cv::Vec3b *Or = frame.ptr<cv::Vec3b>(y);
for (int x = 0; x < input.cols; ++x) {
cv::Vec3b ycrcb = Mr[x];
// Or[x] = (skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) > 0) ? 255 : 0;
if(skinCrCbHist.at<uchar>(ycrcb[1], ycrcb[2]) == 0) {
Or[x] = cv::Vec3b(0,0,0);
}
}
}
return output;
}
/**
* @function detectAndDisplay
*/
void detectAndDisplay( cv::Mat frame ) {
std::vector<cv::Rect> faces;
//initialize
cv::Rect largest_face;
largest_face.width =0;
largest_face.height=0;
//cv::Mat frame_gray;
std::vector<cv::Mat> rgbChannels(3);
cv::split(frame, rgbChannels);
cv::Mat frame_gray = rgbChannels[2];
//cvtColor( frame, frame_gray, CV_BGR2GRAY );
//equalizeHist( frame_gray, frame_gray );
//cv::pow(frame_gray, CV_64F, frame_gray);
//-- Detect faces
face_cascade.detectMultiScale( frame_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, cv::Size(150, 150) );
// findSkin(debugImage);
/*for( int i = 0; i < faces.size(); i++ )
{
rectangle(debugImage, faces[i], 1234);
}*/
//-- Show what you got
if (faces.size() > 0) {
for(int i=0;i<faces.size();i++){
if(faces[i].width > largest_face.width && faces[i].height > largest_face.height){
largest_face.width = faces[i].width;
largest_face.height = faces[i].height;
largest_face.x = faces[i].x;
largest_face.y = faces[i].y;
}
}
//findEyes(frame_gray, faces[0]);
if(Face_Detect(largest_face)){
Motor_Control('r', 2500);
Motor_Control('l', 2500);
Motor_Control('p',50);
}
}
}