目录

六、百度智能云人脸库的创建

七、人脸识别SDK的导入

八、百度云平台的接入


六、百度智能云人脸库的创建

在百度智能云的人脸识别控制台中,申请领取免费资源,在进一步页面中我们选择领取全部免费接口即可

Opencv人脸语义分割_bc

 接下来在左侧公有云服务的应用列表中,创建应用,注意,需要将应用归属选择为个人。3

Opencv人脸语义分割_bc_02

 创建完成后即可看到创建情况:

Opencv人脸语义分割_计算机视觉_03

接下来在可视化人脸库中新建组,上传待识别的照片即可。

Opencv人脸语义分割_opencv_04

七、人脸识别SDK的导入

我们可以使用百度提供的SDK完成人脸信息的上传和比对信息的接收。SDK的下载地址为SDK下载_文字识别SDK_语音识别SDK-百度AI开放平台 (baidu.com), 我们选择人脸识别中的C HTTP SDK进行下载,点击使用说明即可进入该SDK的说明文档。

Opencv人脸语义分割_人工智能_05

 根据SDK的官方文档说明,有五个步骤来使用该SDK:

Opencv人脸语义分割_opencv_06

  1.  下载压缩包
  2. 接下来将下载好的压缩文件解压,并放到我们虚拟机中的对应代码文件处。接下来我们将之前写的main.cpp放到解压好的aip-cpp-sdk-4.16.4文件夹中
  3. 安装依赖库libcurl openssl和jsoncpp,我们使用以下命令依次安装
sudo pkg-get install libcurl4-openssl-dev
sudo pkg-get install openssl
sudo pkg-get install libjsoncpp-dev
g++ main.cpp -o main -lopencv_highgui -lopencv_core -lopencv_imgproc -lopencv_objdetect -lcurl -lcrypto -ljsoncpp -std=c++11
  1. 在main.cpp中加入include "face.h"和using namespace aip
include "face.h"

using namespace aip

如果编译报错base/http.h:23:23: fatal error: json/json.h: 没有这个文件或文件夹,那我们将base文件夹中的http.h文件第23行的#include <json/json.h>改为#include <jsoncpp/json/json.h>

同理,编译报错base/base.h:21:23: fatal error: json/json.h: 没有这个文件或文件夹时,我们将base.h21行中的#include <json/json.h>改为#include <jsoncpp/json/json.h>

编译报错base.utils.h:21:25:fatal error:openssl/evp.h:没有这个文件或文件夹时,需要安装一个新的库文件

sudo apt-get install lib-ssl-dev

八、百度云平台的接入

在之前说的SDK官方文档中,我们按照说明进行。

Opencv人脸语义分割_bc_07

使用刚刚你创建应用时提供的ID,Key和Serect

接下来使用SDK文档中人脸搜索的client.search方法

Opencv人脸语义分割_计算机视觉_08

 该函数的参数为:

Opencv人脸语义分割_Opencv人脸语义分割_09

因此,我们需要先定义一个std::string类型的image和image_type,之前的图片格式是jpg的,所以需要进行一下转换,变成base64格式的

std::string base64Img;
json::value result;

base64Img = base64_encode((char *)jpgBuf.data(), jpgBuf().size());    //格式转换为base64

result = client.search(base64Img, "BASE64", "Student", aip::null);    //这里的"Student"是你之前新建的人脸分组的名称

 上述代码段的前两行需要放在for循环前面,后两行放在for循环内部的imencode函数后即可

接下来编译,会报错找不到函数search,这是因为我们下载的SDK中没有search方法,我们使用下面的代码替换“face.h”中的代码即可。现在即可正常编译运行。

Opencv人脸语义分割_人工智能_10

/**
 * 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

到该部分截止,完整代码为:

#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 successfully!"<<endl;

    // 设置APPID/AK/SK
    std::string app_id = "你的app id";
    std::string api_key = "你的api key";
    std::string secret_key = "你的secret key";

    aip::Face client(app_id, api_key, secret_key);

    Mat img;
    Mat grayImg;
    Mat equalizeImg;
    vector<Rect> faces;
    Mat faceImg;
    vector<uchar> jpgBuf;
    std::string base64Img;
    Json::Value result;

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

    for(;;)
    {
        cap >> img; // get a new img from camera
        cvtColor(img, grayImg, CV_BGR2GRAY); //灰度处理
        equalizeHist(grayImg,equalizeImg); //均衡化处理
        classifier.detectMultiScale(equalizeImg, faces); //检测人脸并返回在facas中
        if(faces.size())
        {
            rectangle(equalizeImg, faces[0], Scalar(255,255,255)); //绘制矩形框
            faceImg = equalizeImg(faces[0]);    
            imencode(".jpg", faceImg, jpgBuf);    //将图片编码为jpg格式后存到jpgBuf中
            base64Img = base64_encode((char *)jpgBuf.data(), jpgBuf.size());    //格式转换为base64
result = client.search(base64Img, "BASE64", "Student", aip::null);    //这里的"Student"是你之前新建的人脸分组的名称


        }
        else
            cout<<"No face detected!"<<endl;

        imshow("video", equalizeImg); //在video窗口中展示图片 
        waitKey(40); //设置帧率(40ms读取一帧)
    }

    return 0;
}