期末大作业 -C语言实现人脸识别(detect faces and eyes by opencv)

/*=============================================================================
#     FileName: Facecheck.cpp
#         Desc: detect faces and eyes by opencv
#       Author: Spike
#   LastChange: 2020.6.16
=============================================================================*/

#include "opencv2/opencv.hpp"
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <Windows.h>

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);

}
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值