/*=============================================================================
=============================================================================*/
using namespace std;
using namespace cv;
void detectAndDraw(Mat& Frame, CascadeClassifier& cascade,CascadeClassifier& nestedCascade,double Scale, bool f);
void hide();
void Start_screen();
void MoveCursor(int x, int y);
int main( int argc, char** argv ) {
//隐藏光标
hide();
//绘制初始界面
Start_screen();
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
printf("\n如若希望退出程序请按下Esc!!!\n\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
//打开摄像头
VideoCapture cap(0);
//摄像头未打开提醒
if (!cap.isOpened()) {
cout << "Couldn't open the camera!" << endl;
return -1;
}
CascadeClassifier cascade, nestedCascade;
//加载级联分类器
cascade.load("C:\\Users\\14103\\Downloads\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
nestedCascade.load("C:\\Users\\14103\\Downloads\\opencv\\sources\\data\\haarcascades\\haarcascade_eye_tree_eyeglasses.xml");
Mat Frame;
while (true) {
//读取图片
cap >> Frame;
//缩放比例
double Scale = 1.2;
Mat Small_Img(Frame.rows / Scale, Frame.cols / Scale, CV_8SC1);
resize(Frame, Frame, Small_Img.size(), 0, 0, INTER_LINEAR);
//识别函数
detectAndDraw(Frame, cascade, nestedCascade, 2, 0);
//按Esc退出程序
int key;
key = waitKey(10);
if (key == 'q' || key == 'Q' || key == 27)
break;
}
return 0;
}
inline void hide() {
CONSOLE_CURSOR_INFO cursor_info = {
1,0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void MoveCursor(int x, int y)//设置光标位置
{
COORD pos = {
x * 2,y };
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos); //设置控制台光标位置
}
inline void Start_screen()
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_BLUE);
MoveCursor(12, 10);
printf("Cpp期末大作业 : 基于Opencv的人脸检测和眼部检测");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
MoveCursor(17, 14);
printf("XXXX 2020.6.8");
MoveCursor(19, 16);
printf("学号 : xxxxxxx");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE);
MoveCursor(20, 20);
printf("按回车键开始");
getchar();
system("cls");
}
void detectAndDraw(Mat& Frame, CascadeClassifier& cascade,CascadeClassifier& nestedCascade,double Scale, bool f)
{
//建立用于存放人脸的向量容器
vector<Rect> face_1, face_2;
//定义7种颜色,用于标记人脸
Scalar colors[] =
{
// 红橙黄绿青蓝紫
CV_RGB(255,0,0),
CV_RGB(255, 97, 0),
CV_RGB(255, 255, 0),
CV_RGB(0, 255, 0),
CV_RGB(255, 97, 0),
CV_RGB(0, 0, 255),
CV_RGB(160, 32, 240),
};
//建立缩小的图片,加快检测速度
Mat gray, Small_Img(cvRound(Frame.rows / Scale), cvRound(Frame.cols / Scale), CV_8UC1);
//因为用的是基于灰度图像的类haar特征,所以要转换成灰度图像
cvtColor(Frame, gray, CV_BGR2GRAY);
//改变图像大小,双线性差值
resize(gray, Small_Img, Small_Img.size(), 1 / Scale, 1 / Scale, INTER_LINEAR);
//直方图均值化
equalizeHist(Small_Img, Small_Img);
//计算执行时间
//t = (double)cvGetTickCount();
//检测人脸
cascade.detectMultiScale(Small_Img, face_1, 1.1, 3, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
//翻转图像
//if (f) {
// cascade.detectMultiScale(Small_Img, face_2, 1.1, 3, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
// for (vector<Rect>::const_iterator r = face_2.begin(); r != face_2.end(); r++)
// face_1.push_back(Rect(r->x, r->y, r->width, r->height));
//
//}
//执行时间检测结束
/*t = (double)cvGetTickCount() - t;
printf("Ttime = %g ms\n", t * 1000 / getTickFrequency());*/
int i = 0;
for (vector<Rect>::const_iterator iter = face_1.begin(); iter != face_1.end(); iter++, i++) {
//圆心
Point center;
//颜色
Scalar color = colors[i % 7];
//半径
int radius;
//计算图像比例
double aspect_ratio = (double)iter->width / iter->height;
if (0.75 < aspect_ratio && aspect_ratio < 1.3) {
//还原尺寸&计算半径
center.x = cvRound((iter->x + iter->width * 0.5) * Scale);
center.y = cvRound((iter->y + iter->height * 0.5) * Scale);
radius = cvRound((iter->width + iter->height) * 0.25 * Scale);
//绘制矩形
rectangle(Frame, cvPoint(cvRound(iter->x * Scale), cvRound(iter->y * Scale)),
cvPoint(cvRound((iter->x + iter->width - 1) * Scale), cvRound((iter->y + iter->height - 1) * Scale)),
color, 3, 8, 0);
//绘制圆形
circle(Frame, center, radius, color, 3, 8, 0);
}
else
rectangle(Frame, cvPoint(cvRound(iter->x * Scale), cvRound(iter->y * Scale)),
cvPoint(cvRound((iter->x + iter->width - 1) * Scale), cvRound((iter->y + iter->height - 1) * Scale)),
color, 3, 8, 0);
vector<Rect> Nested_Objects;
//人眼检测
nestedCascade.detectMultiScale(Small_Img, Nested_Objects, 1.1, 3, 0 | CV_HAAR_SCALE_IMAGE, Size(30, 30));
//避免重复查找
if (nestedCascade.empty())
continue;
for (vector<Rect>::const_iterator Eye_iter = Nested_Objects.begin(); Eye_iter != Nested_Objects.end(); Eye_iter++, i++)
{
Mat smallImgROI;
//还原尺寸&计算半径
center.x = cvRound((Eye_iter->x + Eye_iter->width * 0.5) * Scale);
center.y = cvRound((Eye_iter->y + Eye_iter->height * 0.5) * Scale);
radius = cvRound((Eye_iter->width + Eye_iter->height) * 0.25 * Scale);
// 画圆
circle(Frame, center, radius, color, 3, 8, 0);
}
}
//设置窗口
cv::imshow("XXX的人脸识别窗口", Frame);
}