AI Face 人脸识别考勤机项目

目录

一、项目框架

1、硬件环境

2、软件环境

3、项目原理

 二、初识OpenCV

1、opencv的使用​编辑

2、图像采集(含代码)

3、图像处理(含代码)

4、人脸检测(代码)

三、百度智能云平台接入

1、人脸库的创建与管理

2、人脸识别SDK环境搭建

1.下载:下载链接

 2.解压:将其复制到虚拟机ubuntu系统中,如下,右击,点击提取到此处。

 3.安装依赖库:接着在终端输入命令,安装依赖库libcurl(含http),openssl,json,红色为命令,蓝色可以看到依赖库中含http通信协议。

4. 在编译时记得添加C++11支持(gcc/clang添加编译参数-std=c++11),添加第三方链接参数lcurl、lcrypto、ljsoncpp。编译命令如下:

5.,将main.cpp复制到解压缩的文件夹aip-cpp-sdk中,并在源码中include face.h,引入压缩包中的头文件以使用aip命名空间下的类和方法,using namesace aip。

3、代码实现sdk接入百度智能云平台

 四、JSON数据解析

五、Linux获取系统的时间(什么时候刷的脸)

六、考勤信息记录及显示


ps:虚拟机安装大家参考其他博主,本文不赘述,该文中每一小节的代码部分,均是在上一个小节的基础上进行添加的,且若中途退出虚拟机,重新连接摄像头时,"VideoCapture cap();"该语句中的参数可能会发生变化,有可能是0,也有可能是1,须在终端进行一下操作进行查看,查看过程如下。

一、项目框架

1、硬件环境

计算机、摄像头。

2、软件环境

Linux操作系统(ubuntu)、OpenCV(用于人脸检测)、百度智能云(用于人脸数据分析,识别)。

3、项目原理

首先驱动计算机摄像头进行人脸图像采集,然后通过OpenCV库(Linux系统中安装)进行人脸检测,接着通过计算机将脸部数据上传至百度智能云平台并通过该平台进行对比分析,并显示在屏幕上和保存记录在文件中,最终将对比结果传回计算机(考勤机)。

Ps:通过百度智能云进行人脸图像识别对比分析前,要将公司人员信息(照片,姓名,性别,部门),即人脸库,上传至该平台。

 二、初识OpenCV

1、opencv的使用

下载完成后在终端根目录输入“dbkg -s libopencv-dev”查看Linux操作系统所安装的opencv库版本,在官方文档中下载与下载版本相同的库文档压缩包。

 

 

打开下载的压缩包2.4.9.zip,打开该文件中的index.html文件,就是相关库的具体介绍和例程,大家可以按照例程和项目要求修改代码。

2、图像采集(含代码)

前期准备:将虚拟机usb配置改为3.1

接着在windows系统下打开设备管理器,查看摄像头名字,再到ubuntu系统下点击可移动设备,找到对应摄像头名称,点击连接。如下:

ubuntu终端命令与图像采集代码如下:

/**********ubuntu终端命令行如下******************/

touch main.cpp//新建一个c++文件
vim main.cpp//进入文件,点击i开始编辑,复制下面的代码块,点击esc,输入":wq" 保存退出
g++ main.cpp -o main -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_objdetect//编译
./main//运行



/***************图像采集代码块************/
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
  VideoCapture cap(1); // open the default camera
  if(!cap.isOpened())  // check if we succeeded
  {
    cout<<"Camera open failed"<<endl;
    return -1;
  }  
  
    cout<<"Camera open success"<<endl;   

    Mat img;//搞一个容器来存放采集到的图像
    for(;;)
    {
       cap >> img; // get a new frame from camera
       imshow("video", img);
       waitKey(40);
    }
    
    return 0;
} 

3、图像处理(含代码)

将从摄像头采集到的图像进行灰度化,直方图均衡化等处理,提高检测准确度。

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
  VideoCapture cap(1); // open the default camera
  if(!cap.isOpened())  // check if we succeeded
  {
    cout<<"Camera open failed"<<endl;
    return -1;
  }  
  
    cout<<"Camera open success"<<endl;   

    Mat img;
    Mat grayimg;
    Mat equalizeimg;
    for(;;)
    {
       cap >> img; // get a new frame from camera
       cvtColor(img, grayimg,CV_BGR2GRAY);//灰度化
       equalizeHist(grayimg, equalizeimg);//直方图均衡化
       imshow("video", grayimg);
       waitKey(40);
    }
    
    return 0;
} 

4、人脸检测(代码)

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

int main()
{
  VideoCapture cap(0); // open the default camera
  if(!cap.isOpened())  // check if we succeeded
  {
    cout<<"Camera open failed"<<endl;
    return -1;
  }  
  
    cout<<"Camera open success"<<endl;   

    Mat img;//存放摄像头检测到的人脸图像
    Mat grayimg;//存放灰度化的人脸图像
    Mat equalizeimg;//存放将灰度化后的图像进行直方图均衡化的人脸图像


   //加载opencv库提供的人脸识别训练模型
    CascadeClassifier classifier("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml");

    vector<Rect> allFace;
    Mat faceimg;//存放最后最终矩形框框出来的人脸图像,用以上传到百度智能云进行对比分析
    vector<uchar> jpgBuf;//由于上传到百度智能云进行检测具有文件格式要求,因此定义一个容器用以存放解码后的图像

    for(;;)
    {
       cap >> img; // get a new frame from camera
       cvtColor(img, grayimg,CV_BGR2GRAY);
       equalizeHist(grayimg, equalizeimg);
       classifier.detectMultiScale(equalizeimg,allFace); 
       if(allFace.size())//检测到脸的话,画出白色矩形框
       {
            rectangle(equalizeimg,allFace[0],Scalar(255,255,255));
            faceimg = equalizeimg(allFace[0]);//将最新识别出来且框住的人脸信息复制到该容器中
            imencode(".jpg", faceimg,jpgBuf);//解码操作,将格式转换为.jpg图片格式	
       }

       imshow("video", equalizeimg);
       waitKey(40);
    }
    
    return 0;
} 

三、百度智能云平台接入

1、人脸库的创建与管理

百度智能云人脸识别库建立icon-default.png?t=N7T8http://xn--https-kt3b//blog.csdn.net/weixin_43722052/article/details/114083155#:~:text=1.%E6%90%9C%E7%B4%A2%20%E7%99%BE%E5%BA%A6%E4%BA%91%202.%E7%99%BB%E5%BD%95%E8%B4%A6%E5%8F%B7%2C%E7%84%B6%E5%90%8E%E7%82%B9%E5%87%BB%E7%AB%8B%E5%8D%B3%E5%BA%94%E7%94%A8%203.%E7%84%B6%E5%90%8E%E7%82%B9%E5%87%BB%20%E5%88%9B%E5%BB%BA%20%E5%BA%94%E7%94%A8%204.%E7%84%B6%E5%90%8E%E7%BB%99%E5%BA%94%E7%94%A8%E8%B5%B7%E4%B8%AA%E5%90%8D%E5%AD%97%20%E9%80%89%E6%8B%A9%E9%9C%80%E8%A6%81%E7%9A%84%E5%8A%9F%E8%83%BD%2C%E7%84%B6%E5%90%8E%E7%82%B9%E5%87%BB%E7%AB%8B%E5%8D%B3,6.%E7%84%B6%E5%90%8E%E7%82%B9%E5%87%BB%E6%9F%A5%E7%9C%8B%20%E4%BA%BA%E8%84%B8%E5%BA%93%2C%E7%84%B6%E5%90%8E%E7%82%B9%E5%87%BB%E5%B7%A6%E4%BE%A7%E7%9A%84%E6%96%B0%E5%BB%BA%E5%88%86%E7%BB%84%2C%E8%BF%99%E4%B8%AA%E5%B0%B1%E6%98%AF%20%E4%BA%BA%E8%84%B8%20%E5%88%86%E7%BB%84%E4%BA%86%207.%E7%84%B6%E5%90%8E%E6%96%B0%E5%BB%BA%E5%88%86%E7%BB%84%E4%BB%A5%E5%90%8E%2C%E7%82%B9%E5%87%BB%E5%88%86%E7%BB%84%E8%BF%9B%E5%8E%BB%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%8E%BB%E6%96%B0%E5%BB%BA%E7%94%A8%E6%88%B7%E4%BA%86%208.%E7%84%B6%E5%90%8E%E5%B0%B1%E5%8F%AF%E4%BB%A5%E5%8E%BB%E4%B8%8A%E4%BC%A0%20%E4%BA%BA%E8%84%B8%20%E4%BA%86.%E2%80%8B

2、人脸识别SDK环境搭建

作用是将截取到的图片加密解密通过网络协议上传至百度智能云平台,以及通过平台对比人脸库分析识别结果并将其发送回主机的过程。

安装步骤:

1.下载:下载链接

 2.解压:将其复制到虚拟机ubuntu系统中,如下,右击,点击提取到此处。

 3.安装依赖库:接着在终端输入命令,安装依赖库libcurl(含http),openssl,json,红色为命令,蓝色可以看到依赖库中含http通信协议。

命令:

libcurl库:sudo apt-get install libcurl-dev                    //可以查看安装的版本

             sudo apt-get install libcurl4-openssl-dev              //安装

openssl库:sudo apt-get install openssl                  //可以通过dpkg -s openssl查看该库基本信息

ssl库:sudo apt-get install libssl-dev           //手册中没有,但需要安装的!

json库:sudo apt-get install libjsoncpp-dev          //同样可使用dpkg -s libjsoncpp-dev查看该库基本信息

4. 在编译时记得添加C++11支持(gcc/clang添加编译参数-std=c++11),添加第三方链接参数lcurl、lcrypto、ljsoncpp。编译命令如下:

g++ main.cpp -o main -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_objdetect -std=c++11 -lcurl -lcrypto -ljsoncpp

5.,将main.cpp复制到解压缩的文件夹aip-cpp-sdk中,并在源码中include face.h,引入压缩包中的头文件以使用aip命名空间下的类和方法,using namesace aip。

具体如下:

接着编译main.cpp,会出现错误,我们需要将aip-cpp-sdk/base/中的头文件base.h以及http.h中的#include<json/json.h>修改为#include<jsoncpp/json/json.h>。

3、代码实现sdk接入百度智能云平台

详细步骤和参考文档icon-default.png?t=N7T8https://cloud.baidu.com/doc/FACE/s/Uk37c1r11

新建Client:注意appid,api_key,secret_key与智能云平台应用对应起来

下一步:

代码如下:

#include <iostream>
#include "opencv2/opencv.hpp"
#include "face.h"

using namespace std;
using namespace cv;
using namespace aip;

int main()
{
  VideoCapture cap(0); // open the default camera
  if(!cap.isOpened())  // check if we succeeded
  {
    cout<<"Camera open failed"<<endl;
    return -1;
  }  
  
    cout<<"Camera open success"<<endl;   

    Mat img;
    Mat grayimg;
    Mat equalizeimg;
    
    

    CascadeClassifier classifier("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml");

    vector<Rect> allFace;
    Mat faceimg;
    vector<uchar> jpgBuf;



    // 设置APPID/AK/SK
    std::string app_id = "86142722";
    std::string api_key = "w7gWF54W0HO9aqvQpmX7J4ve";
    std::string secret_key = "y0UqAVBTZ5ksXdsNbXC6ifExMmEnDyiI";

    aip::Face client(app_id, api_key, secret_key);
    
    std::string base64img;


    Json::Value result;

    for(;;)
    {
       cap >> img; // get a new frame from camera
       cvtColor(img, grayimg,CV_BGR2GRAY);
       equalizeHist(grayimg, equalizeimg);
       classifier.detectMultiScale(equalizeimg,allFace); 
       if(allFace.size())
       {
            rectangle(equalizeimg,allFace[0],Scalar(255,255,255));
            faceimg = equalizeimg(allFace[0]);
            imencode(".jpg", faceimg,jpgBuf);
            base64img = base64_encode((char *)jpgBuf.data(), jpgBuf.size());
            // 调用人脸搜索
            result = client.search(base64img, "BASE64", "Teacher", aip::null);
            cout<< result <<endl;
	
       }

       imshow("video", equalizeimg);
       waitKey(40);
    }
    
    return 0;
} 

 编译后会报错:原因是更新后的face.h中没有search,因此我们重新编写一个face.h文件替换掉原来的!face.h内容如下!

 face.h内容!!!!

/**
 * Copyright (c) 2017 Baidu.com, Inc. All Rights Reserved
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 *
 * @author baidu aip
 */

#ifndef __AIP_FACE_H__
#define __AIP_FACE_H__

#include "base/base.h"

namespace aip {

    class Face: public AipBase
    {
    public:

        std::string _faceverify =
            "https://aip.baidubce.com/rest/2.0/face/v4/faceverify";
        
        std::string _detect =
            "https://aip.baidubce.com/rest/2.0/face/v2/detect";
        
        std::string _match =
            "https://aip.baidubce.com/rest/2.0/face/v2/match";
        
        std::string _identify =
            "https://aip.baidubce.com/rest/2.0/face/v2/identify";
        
        std::string _verify =
            "https://aip.baidubce.com/rest/2.0/face/v2/verify";
        
        std::string _user_add =
            "https://aip.baidubce.com/rest/2.0/face/v2/faceset/user/add";
        
        std::string _user_update =
            "https://aip.baidubce.com/rest/2.0/face/v2/faceset/user/update";
        
        std::string _user_delete =
            "https://aip.baidubce.com/rest/2.0/face/v2/faceset/user/delete";
        
        std::string _user_get =
            "https://aip.baidubce.com/rest/2.0/face/v2/faceset/user/get";
        
        std::string _group_getlist =
            "https://aip.baidubce.com/rest/2.0/face/v2/faceset/group/getlist";
        
        std::string _group_getusers =
            "https://aip.baidubce.com/rest/2.0/face/v2/faceset/group/getusers";
        
        std::string _group_adduser =
            "https://aip.baidubce.com/rest/2.0/face/v2/faceset/group/adduser";
        
        std::string _group_deleteuser =
            "https://aip.baidubce.com/rest/2.0/face/v2/faceset/group/deleteuser";

        std::string _face_verify_v4 =
                "https://aip.baidubce.com/rest/2.0/face/v4/mingjing/verify";

        std::string _face_match_v4 =
                "https://aip.baidubce.com/rest/2.0/face/v4/mingjing/match";

        std::string _online_picture_live_v4 = "https://aip.baidubce.com/rest/2.0/face/v4/faceverify";
        
        
        std::string _face_search = "https://aip.baidubce.com/rest/2.0/face/v3/search";
        
        //"https://aip.baidubce.com/rest/2.0/face/capture/search";//

        Face(const std::string & app_id, const std::string & ak, const std::string & sk): AipBase(app_id, ak, sk)
        {
        }

        std::string vector_join_base64(const std::vector<std::string> & v_images) {
            std::string images;
            size_t count = v_images.size();
            for (size_t i = 0; i < count;i++)
            {
                std::string image = v_images[i];
                images += base64_encode(image.c_str(), (int) image.size());
                if (i != count) {
                    images += ",";
                }

            }
            return images;
        }
        
        /**
         * detect
         * @param image 图像文件二进制内容,可以使用aip::get_file_content函数获取
         * options 可选参数:
         * max_face_num 最多处理人脸数目,默认值1
         * face_fields 包括age,beauty,expression,faceshape,gender,glasses,landmark,race,qualities信息,逗号分隔,默认只返回人脸框、概率和旋转角度
         */
        Json::Value detect(
            std::string const & image,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["image"] = base64_encode(image.c_str(), (int) image.size());

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_detect, null, data, null);

            return result;
        }
        
        /**
         * match
         * @param images vector多图图像文件二进制内容,vector中每一项可以使用aip::get_file_content函数获取
         * options 可选参数:
         * ext_fields 返回质量信息,取值固定:目前支持qualities(质量检测)。(对所有图片都会做改处理)
         * image_liveness 返回的活体信息,“faceliveness,faceliveness” 表示对比对的两张图片都做活体检测;“,faceliveness” 表示对第一张图片不做活体检测、第二张图做活体检测;“faceliveness,” 表示对第一张图片做活体检测、第二张图不做活体检测;<br>**注:需要用于判断活体的图片,图片中的人脸像素面积需要不小于100px\*100px,人脸长宽与图片长宽比例,不小于1/3**
         * types 请求对比的两张图片的类型,示例:“7,13”<br>**12**表示带水印证件照:一般为带水印的小图,如公安网小图<br>**7**表示生活照:通常为手机、相机拍摄的人像图片、或从网络获取的人像图片等<br>**13**表示证件照片:如拍摄的身份证、工卡、护照、学生证等证件图片,**注**:需要确保人脸部分不可太小,通常为100px\*100px
         */
        Json::Value match(
            const std::vector<std::string> & images,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["images"] = vector_join_base64(images);

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_match, null, data, null);

            return result;
        }
        
        /**
         * identify
         * @param group_id 用户组id(由数字、字母、下划线组成),长度限制128B,多个用户组id,用逗号分隔
         * @param image 图像文件二进制内容,可以使用aip::get_file_content函数获取
         * options 可选参数:
         * ext_fields 特殊返回信息,多个用逗号分隔,取值固定: 目前支持faceliveness(活体检测)。**注:需要用于判断活体的图片,图片中的人脸像素面积需要不小于100px\*100px,人脸长宽与图片长宽比例,不小于1/3**

         * user_top_num 返回用户top数,默认为1,最多返回5个
         */
        Json::Value identify(
            std::string const & group_id,
            std::string const & image,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["group_id"] = group_id;
            data["image"] = base64_encode(image.c_str(), (int) image.size());

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_identify, null, data, null);

            return result;
        }
        
        /**
         * verify
         * @param uid 用户id(由数字、字母、下划线组成),长度限制128B
         * @param image 图像文件二进制内容,可以使用aip::get_file_content函数获取
         * @param group_id 用户组id(由数字、字母、下划线组成),长度限制128B,多个用户组id,用逗号分隔
         * options 可选参数:
         * top_num 返回用户top数,默认为1
         * ext_fields 特殊返回信息,多个用逗号分隔,取值固定: 目前支持faceliveness(活体检测)。**注:需要用于判断活体的图片,图片中的人脸像素面积需要不小于100px\*100px,人脸长宽与图片长宽比例,不小于1/3**

         */
        Json::Value verify(
            std::string const & uid,
            std::string const & image,
            std::string const & group_id,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["uid"] = uid;
            data["image"] = base64_encode(image.c_str(), (int) image.size());
            data["group_id"] = group_id;

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_verify, null, data, null);

            return result;
        }
        
        /**
         * user_add
         * @param uid 用户id(由数字、字母、下划线组成),长度限制128B
         * @param user_info 用户资料,长度限制256B
         * @param group_id 用户组id,标识一组用户(由数字、字母、下划线组成),长度限制128B。如果需要将一个uid注册到多个group下,group\_id需要用多个逗号分隔,每个group_id长度限制为48个英文字符。**注:group无需单独创建,注册用户时则会自动创建group。**<br>**产品建议**:根据您的业务需求,可以将需要注册的用户,按照业务划分,分配到不同的group下,例如按照会员手机尾号作为groupid,用于刷脸支付、会员计费消费等,这样可以尽可能控制每个group下的用户数与人脸数,提升检索的准确率
         * @param image 图像文件二进制内容,可以使用aip::get_file_content函数获取
         * options 可选参数:
         * action_type 参数包含append、replace。**如果为“replace”,则每次注册时进行替换replace(新增或更新)操作,默认为append操作**。例如:uid在库中已经存在时,对此uid重复注册时,新注册的图片默认会**追加**到该uid下,如果手动选择`action_type:replace`,则会用新图替换库中该uid下所有图片。
         */
        Json::Value user_add(
            std::string const & uid,
            std::string const & user_info,
            std::string const & group_id,
            std::string const & image,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["uid"] = uid;
            data["user_info"] = user_info;
            data["group_id"] = group_id;
            data["image"] = base64_encode(image.c_str(), (int) image.size());

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_user_add, null, data, null);

            return result;
        }
        
        /**
         * user_update
         * @param uid 用户id(由数字、字母、下划线组成),长度限制128B
         * @param image 图像文件二进制内容,可以使用aip::get_file_content函数获取
         * @param user_info 用户资料,长度限制256B
         * @param group_id 更新指定groupid下uid对应的信息
         * options 可选参数:
         * action_type 目前仅支持replace,uid不存在时,不报错,会自动变为注册操作;未选择该参数时,如果uid不存在会提示错误
         */
        Json::Value user_update(
            std::string const & uid,
            std::string const & image,
            std::string const & user_info,
            std::string const & group_id,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["uid"] = uid;
            data["image"] = base64_encode(image.c_str(), (int) image.size());
            data["user_info"] = user_info;
            data["group_id"] = group_id;

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_user_update, null, data, null);

            return result;
        }
        
        /**
         * user_delete
         * @param uid 用户id(由数字、字母、下划线组成),长度限制128B
         * @param group_id 删除指定groupid下uid对应的信息
         * options 可选参数:
         */
        Json::Value user_delete(
            std::string const & uid,
            std::string const & group_id,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["uid"] = uid;
            data["group_id"] = group_id;

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_user_delete, null, data, null);

            return result;
        }
        
        /**
         * user_get
         * @param uid 用户id(由数字、字母、下划线组成),长度限制128B
         * options 可选参数:
         * group_id 选择指定group_id则只查找group列表下的uid内容,如果不指定则查找所有group下对应uid的信息
         */
        Json::Value user_get(
            std::string const & uid,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["uid"] = uid;

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_user_get, null, data, null);

            return result;
        }
        
        /**
         * group_getlist
         * options 可选参数:
         * start 默认值0,起始序号
         * end 返回数量,默认值100,最大值1000
         */
        Json::Value group_getlist(
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_group_getlist, null, data, null);

            return result;
        }
        
        /**
         * group_getusers
         * @param group_id 用户组id(由数字、字母、下划线组成),长度限制128B
         * options 可选参数:
         * start 默认值0,起始序号
         * end 返回数量,默认值100,最大值1000
         */
        Json::Value group_getusers(
            std::string const & group_id,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["group_id"] = group_id;

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_group_getusers, null, data, null);

            return result;
        }
        
        /**
         * group_adduser
         * @param group_id 用户组id(由数字、字母、下划线组成),长度限制128B,多个用户组id,用逗号分隔
         * @param uid 用户id(由数字、字母、下划线组成),长度限制128B
         * @param src_group_id 从指定group里复制信息
         * options 可选参数:
         */
        Json::Value group_adduser(
            std::string const & group_id,
            std::string const & uid,
            std::string const & src_group_id,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["group_id"] = group_id;
            data["uid"] = uid;
            data["src_group_id"] = src_group_id;

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_group_adduser, null, data, null);

            return result;
        }
        
        /**
         * group_deleteuser
         * @param group_id 用户组id(由数字、字母、下划线组成),长度限制128B,多个用户组id,用逗号分隔
         * @param uid 用户id(由数字、字母、下划线组成),长度限制128B
         * options 可选参数:
         */
        Json::Value group_deleteuser(
            std::string const & group_id,
            std::string const & uid,
            const std::map<std::string, std::string> & options)
        {
            std::map<std::string, std::string> data;
            
            data["group_id"] = group_id;
            data["uid"] = uid;

            std::copy(options.begin(), options.end(), std::inserter(data, data.end()));

            Json::Value result =
                this->request(_group_deleteuser, null, data, null);

            return result;
        }

        /**
         * 人脸 - 人脸实名认证V4
         * 基于姓名和身份证号,调取公安权威数据源人脸图,将当前获取的人脸图片,与此公安数据源人脸图进行对比,得出比对分数,并基于此进行业务判断是否为同一人
         * @param idCardNumber 身份证件号
         * @param name 姓名(需要是 utf8 编码)
         * @param image 图片信息(数据大小应小于10M 分辨率应小于1920*1080),5.2版本SDK请求时已包含在加密数据data中,无需额外传入
         * options 可选参数:
         * quality_control 质量控制参数
         */
        Json::Value faceMingJingVerify(
            const std::string& idCardNumber,
            const std::string& name,
            std::string* image,
            std::map<std::string, std::string> options)
        {
            std::string access_token = this->getAccessToken();

            Json::Value data;
            data["id_card_number"] = idCardNumber;
            data["name"] = name;
            if (image != nullptr) {
                data["image"] = *image;
            }

            std::map< std::string,std::string >::iterator it ;
            for(it = options.begin(); it != options.end(); it++)
            {
                data[it->first] = it->second;
            }
            std::string mid = "?access_token=";
            std::string url = _face_verify_v4 + mid + access_token;
            Json::Value result =
                this->request_com(url, data);

            return result;
        }

        /**
         * 人脸 - 人脸对比V4
         * 用于比对多张图片中的人脸相似度并返回两两比对的得分,可用于判断两张脸是否是同一人的可能性大小
         * @param image 图片信息(数据大小应小于10M 分辨率应小于1920*1080),5.2版本SDK请求时已包含在加密数据data中,无需额外传入
         * @param imageType 图片类型
         * @param registerImage 图片信息(总数据大小应小于10M),图片上传方式根据image_type来判断。本图片特指客户服务器上传图片,非加密图片Base64值
         * @param registerImageType 图片类型
         * options 可选参数
         */
        Json::Value faceMingJingMatch(
            std::string * image,
            std::string * imageType,
            const std::string& registerImage,
            const std::string& registerImageType,
            std::map<std::string, std::string>  options)
        {
            std::string access_token = this->getAccessToken();

            Json::Value data;
            if (image != nullptr) {
                data["image"] = *image;
            }
            if (imageType != nullptr) {
                data["image_type"] = *imageType;
            }
            data["register_image"] = registerImage;
            data["register_image_type"] = registerImageType;

            std::map< std::string,std::string >::iterator it ;
            for(it = options.begin(); it != options.end(); it++)
            {
                data[it->first] = it->second;
            }
            std::string mid = "?access_token=";
            std::string url = _face_match_v4 + mid + access_token;
            Json::Value result =
                this->request_com(url, data);

            return result;
        }

        /**
         * 人脸 - 在线图片活体V4
         * 基于单张图片,判断图片中的人脸是否为二次翻拍
         * @param sdkVersion sdk版本
         * options 可选参数
         */
        Json::Value onlinePictureLiveV4(
            const std::string& sdkVersion,
            std::vector<std::string>& imageList,
            std::map<std::string, std::string>  options)
        {
            std::string access_token = this->getAccessToken();

            Json::Value data;
            data["sdk_version"] = sdkVersion;
            Json::Value imageListJson;
            for (std::string image : imageList) {
                imageListJson.append(image);
            }
            data["image_list"] = imageListJson;

            std::map< std::string,std::string >::iterator it ;
            for(it = options.begin(); it != options.end(); it++)
            {
                data[it->first] = it->second;
            }
            std::string mid = "?access_token=";
            std::string url = _online_picture_live_v4 + mid + access_token;
            Json::Value result =
                this->request_com(url, data);

            return result;
        }
        
        
        Json::Value search(
            std::string const & image,
            std::string const & imageType,
            std::string const & group_id,
            const std::map<std::string, std::string> & options)
        {
            std::string access_token = this->getAccessToken();

            Json::Value data;

            data["image"] = image;
            data["image_type"] = imageType;
            data["group_id_list"] = group_id;

            std::string mid = "?access_token=";
            std::string url = _face_search + mid + access_token;
            Json::Value result =
                this->request_com(url, data);

            return result;
        }

    };
}
#endif

 替换后,再次编译,完成后输入命令./main运行,成功识别!!

 四、JSON数据解析

截止到上述步骤结束后,只是实现了将识别到的人脸信息打印到终端。我们需要解析提取出我们想要的信息,去除冗余的信息!

我们需要的信息如下:

error_msg=success

success  score>80

user_id=...

代码:

#include <iostream>
#include "opencv2/opencv.hpp"
#include "face.h"

using namespace std;
using namespace cv;
using namespace aip;

int main()
{
  VideoCapture cap(0); // open the default camera
  if(!cap.isOpened())  // check if we succeeded
  {
    cout<<"Camera open failed"<<endl;
    return -1;
  }  
  
    cout<<"Camera open success"<<endl;   

    Mat img;
    Mat grayimg;
    Mat equalizeimg;
    
    

    CascadeClassifier classifier("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml");

    vector<Rect> allFace;
    Mat faceimg;
    vector<uchar> jpgBuf;



    // 设置APPID/AK/SK
    std::string app_id = "86142722";
    std::string api_key = "w7gWF54W0HO9aqvQpmX7J4ve";
    std::string secret_key = "y0UqAVBTZ5ksXdsNbXC6ifExMmEnDyiI";

    aip::Face client(app_id, api_key, secret_key);
    
    std::string base64img;


    Json::Value result;

    for(;;)
    {
       cap >> img; // get a new frame from camera
       cvtColor(img, grayimg,CV_BGR2GRAY);
       equalizeHist(grayimg, equalizeimg);
       classifier.detectMultiScale(equalizeimg,allFace); 
       if(allFace.size())
       {
            rectangle(equalizeimg,allFace[0],Scalar(255,255,255));
            faceimg = equalizeimg(allFace[0]);
            imencode(".jpg", faceimg,jpgBuf);
            base64img = base64_encode((char *)jpgBuf.data(), jpgBuf.size());
            // 调用人脸搜索
            result = client.search(base64img, "BASE64", "Teacher", aip::null);
            
            //提取有用的
            if(!result["result"].isNull())
            {
                if(result["result"]["user_list"][0]["score"].asInt() > 80)
                {
                     cout<< result["result"]["user_list"][0]["user_id"] <<endl;
                }

            }
            
	
       }

       imshow("video", equalizeimg);
       waitKey(40);
    }
    
    return 0;
} 

五、Linux获取系统的时间(什么时候刷的脸)

代码:

#include <iostream>
#include "opencv2/opencv.hpp"
#include "face.h"

using namespace std;
using namespace cv;
using namespace aip;

int main()
{
  VideoCapture cap(0); // open the default camera
  if(!cap.isOpened())  // check if we succeeded
  {
    cout<<"Camera open failed"<<endl;
    return -1;
  }  
  
    cout<<"Camera open success"<<endl;   

    Mat img;
    Mat grayimg;
    Mat equalizeimg;
    
    

    CascadeClassifier classifier("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml");

    vector<Rect> allFace;
    Mat faceimg;
    vector<uchar> jpgBuf;



    // 设置APPID/AK/SK
    std::string app_id = "86142722";
    std::string api_key = "w7gWF54W0HO9aqvQpmX7J4ve";
    std::string secret_key = "y0UqAVBTZ5ksXdsNbXC6ifExMmEnDyiI";

    aip::Face client(app_id, api_key, secret_key);
    
    std::string base64img;


    Json::Value result;

    time_t sec;

    for(;;)
    {
       cap >> img; // get a new frame from camera
       cvtColor(img, grayimg,CV_BGR2GRAY);
       equalizeHist(grayimg, equalizeimg);
       classifier.detectMultiScale(equalizeimg,allFace); 
       if(allFace.size())
       {
            rectangle(equalizeimg,allFace[0],Scalar(255,255,255));
            faceimg = equalizeimg(allFace[0]);
            imencode(".jpg", faceimg,jpgBuf);
            base64img = base64_encode((char *)jpgBuf.data(), jpgBuf.size());
            // 调用人脸搜索
            result = client.search(base64img, "BASE64", "Teacher", aip::null);
            
            if(!result["result"].isNull())
            {
                if(result["result"]["user_list"][0]["score"].asInt() > 80)
                {
                     cout<< result["result"]["user_list"][0]["user_id"] <<endl;
                     sec = time(NULL);
                     cout<<ctime(&sec)<<endl;
                     
                }

            }
            
	
       }

       imshow("video", equalizeimg);
       waitKey(40);
    }
    
    return 0;
} 

运行结果:

六、考勤信息记录及显示

上述完成后,关闭后,考勤信息就会消失,一般用文件io记录考勤信息,但学习它须花费几天时间。我们采取另一种方式:输出重定向,将输出的信息打印保存记录到某一个文件中。

我们会在目录中发现多出了log.txt文件,如下:

但此时终端中不会出现任何输出信息,导致我们无法知道有没有打卡成功,因此须将考勤信息显示在窗口上。

最终完整代码:

#include <iostream>
#include "opencv2/opencv.hpp"
#include "face.h"

using namespace std;
using namespace cv;
using namespace aip;

int main()
{
  VideoCapture cap(0); // open the default camera
  if(!cap.isOpened())  // check if we succeeded
  {
    cout<<"Camera open failed"<<endl;
    return -1;
  }  
  
    cout<<"Camera open success"<<endl;   

    Mat img;
    Mat grayimg;
    Mat equalizeimg;
    
    

    CascadeClassifier classifier("/usr/share/opencv/haarcascades/haarcascade_frontalface_alt2.xml");

    vector<Rect> allFace;
    Mat faceimg;
    vector<uchar> jpgBuf;



    // 设置APPID/AK/SK
    std::string app_id = "86142722";
    std::string api_key = "w7gWF54W0HO9aqvQpmX7J4ve";
    std::string secret_key = "y0UqAVBTZ5ksXdsNbXC6ifExMmEnDyiI";

    aip::Face client(app_id, api_key, secret_key);
    
    std::string base64img;


    Json::Value result;

    time_t sec;

    for(;;)
    {
       cap >> img; // get a new frame from camera
       cvtColor(img, grayimg,CV_BGR2GRAY);
       equalizeHist(grayimg, equalizeimg);
       classifier.detectMultiScale(equalizeimg,allFace); 
       if(allFace.size())
       {
            rectangle(equalizeimg,allFace[0],Scalar(255,255,255));
            faceimg = equalizeimg(allFace[0]);
            imencode(".jpg", faceimg,jpgBuf);
            base64img = base64_encode((char *)jpgBuf.data(), jpgBuf.size());
            // 调用人脸搜索
            result = client.search(base64img, "BASE64", "Teacher", aip::null);
            
            if(!result["result"].isNull())
            {
                if(result["result"]["user_list"][0]["score"].asInt() > 80)
                {
                     cout<< result["result"]["user_list"][0]["user_id"] <<endl;
                     sec = time(NULL);
                     cout<<ctime(&sec)<<endl;
                     putText(equalizeimg,result["result"]["user_list"][0]["user_id"].asString() , Point (0,50), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255,255,255));
                     putText(equalizeimg,ctime(&sec) , Point (0,100), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(255,255,255));
                }

            }
            
	
       }

       imshow("video", equalizeimg);
       waitKey(40);
    }
    
    return 0;
} 

实现效果:

  • 32
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
当然可以帮你写一个基于AI人脸识别考勤机项目代码。以下是一个示例代码,使用Python和OpenCV库来实现: ```python import cv2 import face_recognition import os # 加载已知人脸图像并编码 known_faces_encodings = [] known_faces_names = [] # 遍历已知人脸图像文件夹,并加载每个人脸图像进行编码 known_faces_dir = 'known_faces/' for filename in os.listdir(known_faces_dir): if filename.endswith('.jpg') or filename.endswith('.png'): face_image = face_recognition.load_image_file(known_faces_dir + filename) face_encoding = face_recognition.face_encodings(face_image)[0] known_faces_encodings.append(face_encoding) known_faces_names.append(os.path.splitext(filename)[0]) # 初始化摄像头 video_capture = cv2.VideoCapture(0) while True: # 读取当前帧 ret, frame = video_capture.read() # 缩小帧以加快人脸识别 small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) # 将图像从BGR颜色空间转换为RGB颜色空间 rgb_small_frame = cv2.cvtColor(small_frame, cv2.COLOR_BGR2RGB) # 在当前帧中查找人脸位置和编码 face_locations = face_recognition.face_locations(rgb_small_frame) face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) # 在当前帧中匹配已知人脸 face_names = [] for face_encoding in face_encodings: matches = face_recognition.compare_faces(known_faces_encodings, face_encoding) name = "Unknown" # 如果找到了匹配的已知人脸,则使用已知人脸的名称 if True in matches: match_index = matches.index(True) name = known_faces_names[match_index] face_names.append(name) # 在当前帧中绘制人脸边界框和名称 for (top, right, bottom, left), name in zip(face_locations, face_names): # 恢复由0.25缩放的框架的原始大小 top *= 4 right *= 4 bottom *= 4 left *= 4 # 绘制人脸边界框 cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2) # 在人脸下方绘制姓名 cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED) font = cv2.FONT_HERSHEY_DUPLEX cv2.putText(frame, name, (left + 6, bottom - 6), font, 0.7, (255, 255, 255), 1) # 显示结果图像 cv2.imshow('Video', frame) # 按 'q' 键退出 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放摄像头和关闭窗口 video_capture.release() cv2.destroyAllWindows() ``` 这个示例代码使用了face_recognition库来进行人脸检测和识别,通过摄像头实时检测人脸并与已知人脸进行比对,最后在识别到的人脸上方显示姓名。你需要提前准备一个包含已知人脸图像的文件夹,并将其路径设置为`known_faces_dir`。你可以将已知人脸的图像文件放在该文件夹中,并按照文件名来命名人脸。注意,这只是一个简单的示例,实际应用中可能需要更复杂的逻辑和功能来满足实际需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值