基于相关系数的影像匹配_级联分类器实战- 模板匹配与人眼检测相结合实现人眼跟踪...

40ad633c05f8da3a3f830cf1964f7a48.png

1.HAAR级联分类器实现人的眼睛检测

1.1 人脸的生物学特征

  • 两个眼睛之间的宽度大致等于一个眼睛的距离
  • 左右对称
  • 眼睛到嘴巴之间的距离大致在两个眼睛的宽度大小左右
  • 鼻子到嘴巴距离大致等于两个嘴唇的厚度

先检测到人脸,然后截取人脸的一半区域(眼睛在脸的上半部分),而上半部分又可以平均分割成左右两边,还可以在细化把这个上半部分分成四份,最上面的四分之一可以去掉,还可以把人脸的横方向分为八分,八分之一的地方可以去掉。当找到人的眼睛之后,可以把它保存起来当做模板,利用模板匹配实现在下一次(下一帧)的跟踪,这样可以减少计算量,而且准确度会更高。

4343c2d225a8843b1a158d536fc2ad9e.png

1.2 人眼检测

例子代码:

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;

// haarcascade_lefteye_2splits.xml  haarcascade_righteye_2splits.xml
string facefile = "D:/opencv33_contrib/etc/haarcascades/haarcascade_frontalface_alt.xml";
//string lefteyefile = "D:/opencv33_contrib/etc/haarcascades/haarcascade_eye.xml";
//string righteyefile = "D:/opencv33_contrib/etc/haarcascades/haarcascade_eye.xml";
string lefteyefile = "D:/opencv33_contrib/etc/haarcascades/haarcascade_lefteye_2splits.xml";
string righteyefile = "D:/opencv33_contrib/etc/haarcascades/haarcascade_righteye_2splits.xml";
CascadeClassifier face_detector;
CascadeClassifier leftyeye_detector;
CascadeClassifier righteye_detector;

Rect leftEye, rightEye;  //用于保存检测到的左右眼

void trackEye(Mat &inputImg,Mat &tplImg,Rect &rect)
{
    //模板匹配固定写法
    Mat result;
    int result_cols = inputImg.cols - tplImg.cols + 1;
    int result_rows = inputImg.rows - tplImg.rows + 1;

    //模板匹配
    result.create(result_rows, result_cols, CV_32FC1);
    //TM_CCORR_NORMED相关系数 模板匹配比较方法
    matchTemplate(inputImg, tplImg, result, TM_CCORR_NORMED);  

    //寻找位置
    double minval, maxval;
    Point minloc, maxloc;
    minMaxLoc(result, &minval, &maxval, &minloc, &maxloc);
    if (maxval > 0.75)  //相关系数大于 0.75时,模板匹配成功
    {
        rect.x = rect.x + maxloc.x;
        rect.y = rect.y + maxloc.y;
    }
    else  //没找到时全部设置为 0 
    {
        rect.x = rect.y = rect.width = rect.height = 0;
    }
}

void test()
{

    //VideoCapture capture(0);  //打开摄像头
    VideoCapture capture("01.mp4");
    if (!capture.isOpened())
    {
        cout << "could not load video data...n" << endl;
    }
    Mat frame, grayImg;
    vector<Rect> faces;
    vector<Rect> eyes;

    if (!face_detector.load(facefile))
    {
        cout << "could not load face feature data...n" << endl;
    }
    if (!leftyeye_detector.load(lefteyefile))
    {
        cout << "could not load leftyeye feature data...n" << endl;
    }
    if (!righteye_detector.load(righteyefile)) 
    {
        cout << "could not load righteye feature data...n" << endl;
    }

    namedWindow("result", CV_WINDOW_NORMAL);

    Mat lefttpl, righttpl; // 模板
    while (capture.read(frame)) 
    {

        cvtColor(frame, grayImg, COLOR_BGR2GRAY);
        equalizeHist(grayImg, grayImg);
        face_detector.detectMultiScale(grayImg, faces, 1.1, 4, 0, Size(48, 48));
        for (int i = 0; i < faces.size(); i++) 
        {
            rectangle(frame, faces[i], Scalar(255, 0, 0), 2, 8, 0);

            // 计算 offset ROI
            int offsety = faces[i].height / 4;
            int offsetx = faces[i].width / 8;
            int eyeheight = faces[i].height / 2 - offsety;
            int eyewidth = faces[i].width / 2 - offsetx;

            // 截取左眼区域
            Rect leftRect;
            leftRect.x = faces[i].x + offsetx;
            leftRect.y = faces[i].y + offsety;
            leftRect.width = eyewidth;
            leftRect.height = eyeheight;
            Mat leftRoi = grayImg(leftRect);

            // 检测左眼
            leftyeye_detector.detectMultiScale(leftRoi, eyes, 1.1, 0, 0, Size(20, 20));
            if (lefttpl.empty())  //如果发现模板为空的话,就去计算得到模板
            {
                if (eyes.size()) 
                {
                    //检测眼睛矩形平移
                    leftRect = eyes[0] + Point(leftRect.x, leftRect.y);
                    lefttpl = grayImg(leftRect);  //获取左眼的模板存到 righttpl 中
                    rectangle(frame, leftRect, Scalar(0, 0, 255), 2, 8, 0);
                }
            }
            else  //不为空,就调用模板
            {
                // 跟踪, 基于模板匹配
                leftEye.x = leftRect.x;  //初始化
                leftEye.y = leftRect.y;

                //leftRoi 获取的眼睛图 lefttpl 模板数据 leftEye 结果图
                trackEye(leftRoi, lefttpl, leftEye);  
                if (leftEye.x > 0 && leftEye.y > 0) 
                {
                    //设置宽度和高度,再画出来
                    leftEye.width = lefttpl.cols;  
                    leftEye.height = lefttpl.rows;
                    rectangle(frame, leftEye, Scalar(0, 0, 255), 2, 8, 0);
                }
            }

            // 截取右眼区域
            Rect rightRect;
            rightRect.x = faces[i].x + faces[i].width / 2;
            rightRect.y = faces[i].y + offsety;
            rightRect.width = eyewidth;
            rightRect.height = eyeheight;
            Mat rightRoi = grayImg(rightRect);

            // 检测右眼
            righteye_detector.detectMultiScale(rightRoi, eyes, 1.1, 0, 0, Size(20, 20));
            if (righttpl.empty())
            {
                if (eyes.size()) 
                {
                    rightRect = eyes[0] + Point(rightRect.x, rightRect.y);
                    righttpl = grayImg(rightRect);  //获取右眼的模板存到 righttpl 中
                    rectangle(frame, rightRect, Scalar(0, 255, 255), 2, 8, 0);
                }
            }
            else
            {
                // 跟踪, 基于模板匹配
                rightEye.x = rightRect.x;
                rightEye.y = rightRect.y;
                trackEye(rightRoi, righttpl, rightEye);
                if (rightEye.x > 0 && rightEye.y > 0) 
                {
                    rightEye.width = righttpl.cols;
                    rightEye.height = righttpl.rows;
                    rectangle(frame, rightEye, Scalar(0, 255, 255), 2, 8, 0);
                }
            }
        }

        imshow("result", frame);
        char c = waitKey(100);
        if (c == 27)
        {
            break;
        }
    }
    capture.release();
}
int main()
{
    test();
    waitKey(0);
    return 0;
}

效果:

Video_eyes_detector​v.youku.com
d876616cbb5f5e98da07c2f2203c56ab.png

1.3 猫脸检测

例子代码:

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;

//haarcascade_frontalcatface.xml 猫脸检测
string catfile = "D:/opencv33_contrib/etc/haarcascades/haarcascade_frontalcatface.xml";
CascadeClassifier catface_detector;

void test()
{
    if (!catface_detector.load(catfile))
    {
        cout << "could not load catface feature data...n" << endl; 
    }

    Mat srcImg = imread("cat3.jpg");
    if (srcImg.empty())
    {
        cout << "could not load image...n" << endl;
    }

    Mat grayImg;
    vector<Rect> cats;
    cvtColor(srcImg, grayImg, COLOR_BGR2GRAY);
    equalizeHist(grayImg, grayImg);

    catface_detector.detectMultiScale(grayImg, cats, 
        1.1, 
        1,  //相邻的矩形窗口要达到或者超过这个参数,才保留。
        0,
        Size(24, 24));  //可以接受的最小窗口尺寸,如果小于这个它就不会考虑成猫脸

    for (int i = 0; i < cats.size(); i++)
    {
        rectangle(srcImg, cats[i], Scalar(0, 255, 0), 2, 8, 0);
    }

    namedWindow("Cat Face Detector Demo", CV_WINDOW_AUTOSIZE);
    imshow("Cat Face Detector Demo", srcImg);
}

int main()
{
    test();
    waitKey(0);
    return 0;
}

效果图:

5508a27c05d367ed5b2cde573fd33a31.png

472cfeac7e10a68b5224ec2a9f21ba84.png

欢迎关注我的微信公众号“OpenCV图像处理算法”,主要是记录自己学习图像处理算法的历程,包括特征提取、目标跟踪、定位、机器学习和深度学习,每一个例子都会提供源码和例子所用的资料,欢迎同行的同学关注我和我一起虚度光阴吧!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于微信小程序的家政服务预约系统采用PHP语言和微信小程序技术,数据库采用Mysql,运行软件为微信开发者工具。本系统实现了管理员和客户、员工三个角色的功能。管理员的功能为客户管理、员工管理、家政服务管理、服务预约管理、员工风采管理、客户需求管理、接单管理等。客户的功能为查看家政服务进行预约和发布自己的需求以及管理预约信息和接单信息等。员工可以查看预约信息和进行接单。本系统实现了网上预约家政服务的流程化管理,可以帮助工作人员的管理工作和帮助客户查询家政服务的相关信息,改变了客户找家政服务的方式,提高了预约家政服务的效率。 本系统是针对网上预约家政服务开发的工作管理系统,包括到所有的工作内容。可以使网上预约家政服务的工作合理化和流程化。本系统包括手机端设计和电脑端设计,有界面和数据库。本系统的使用角色分为管理员和客户、员工三个身份。管理员可以管理系统里的所有信息。员工可以发布服务信息和查询客户的需求进行接单。客户可以发布需求和预约家政服务以及管理预约信息、接单信息。 本功能可以实现家政服务信息的查询和删除,管理员添加家政服务信息功能填写正确的信息就可以实现家政服务信息的添加,点击家政服务信息管理功能可以看到基于微信小程序的家政服务预约系统里所有家政服务的信息,在添加家政服务信息的界面里需要填写标题信息,当信息填写不正确就会造成家政服务信息添加失败。员工风采信息可以使客户更好的了解员工。员工风采信息管理的流程为,管理员点击员工风采信息管理功能,查看员工风采信息,点击员工风采信息添加功能,输入员工风采信息然后点击提交按钮就可以完成员工风采信息的添加。客户需求信息关系着客户的家政服务预约,管理员可以查询和修改客户需求信息,还可以查看客户需求的添加时间。接单信息属于本系统里的核心数据,管理员可以对接单的信息进行查询。本功能设计的目的可以使家政服务进行及时的安排。管理员可以查询员工信息,可以进行修改删除。 客户可以查看自己的预约和修改自己的资料并发布需求以及管理接单信息等。 在首页里可以看到管理员添加和管理的信息,客户可以在首页里进行家政服务的预约和公司介绍信息的了解。 员工可以查询客户需求进行接单以及管理家政服务信息和留言信息、收藏信息等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值