目录
[2.1 获取API的密钥](#2.1 获取API的密钥)
[2.2 创建人员库](#2.2 创建人员库)
[2.3 配置API](#2.3 配置API)
[2.4 编写接口](#2.4 编写接口)
1.业务逻辑
首先居民需要录入自己的人脸,在采集人脸中录入,随后人脸图片进入腾讯云的人员库和服务器的数据库。


上传成功后如图:

2.代码实现
2.1 获取API的密钥
首先进入控制台总览,然后搜索访问管理:


新建密钥后记得保存密钥,key一旦创建完成,就不会再显示。
2.2 创建人员库
搜索人脸识别:

找到人员管理,然后新建人员库:

按照要求填写必填项,其中人员库id需要配置在配置文件当中

2.3 配置API
在上面的工作都完成之后,就可以进行代码编写了
封装了一个Api参数类,用来读取配置文件中关于腾讯云接口的一些参数:
java
package com.qcby.config;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ConfigurationProperties(value="plateocr")
@Component
@Data
@ApiModel(value = "ApiConfiguration",description = "人脸识别参数描述")
public class ApiConfiguration {
@ApiModelProperty("人脸识别secretId")
private String secretId;
@ApiModelProperty("人脸识别secretKey")
private String secretKey;
// 服务器ip
@ApiModelProperty("人脸识别服务器ip")
private String serverIp;
// 服务器区域
@ApiModelProperty("人脸识别服务器区域")
private String area;
// 默认分组
@ApiModelProperty("人脸识别默认分组")
private String groupId;
// 用户id前缀
@ApiModelProperty("人脸识别用户id前缀")
private String personIdPre;
// 随机数
@ApiModelProperty("人脸识别随机数")
private String nonceStr;
// 是否使用
@ApiModelProperty("人脸识别,是否启用人脸识别功能")
private boolean used = false;
// 识别准确率
@ApiModelProperty("人脸识别比对准确度,如符合80%就识别通过")
private float passPercent;
}
同时在配置文件中配置:
secret-id和key需要在腾讯云的人脸控制台中获取
used是是否开启识别,需要的话就是true
server-ip:域名是 API 的接入点,并不代表产品或者接口实际提供服务的地域,接口支持的地域如下:
area:ap-地区,例如ap-beijing
group-id:人员库的id。在上一步获取到了
pass-percent:识别的严格度,例如这个值是80%,现有人脸和人员库人脸对比符合80%就可以通过
person-id-pre:人员库当中人员id的前缀,我加上了user_,假如入库的人员id=9,那么这个人在我的人员库id就是user_9。

java
#配置人脸识别Api
plateocr:
secret-id: AKIDQsHXbTDmETXR9ey68yb1INErSxa9Zpsr
secret-key: sXzDG8oGUYQ6cx74oKgplTyIPIySkpjS
used: true
server-ip: iai.tencentcloudapi.com
area: ap-guangzhou
group-id: AiCommunity
pass-percent: 0.8
person-id-pre: user_
2.4 编写接口
工具类FaceApi:
java
package com.qcby.util;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qcby.config.ApiConfiguration;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.iai.v20180301.IaiClient;
import com.tencentcloudapi.iai.v20180301.models.*;
import org.apache.log4j.Logger;
public class FaceApi {
private Logger logger = Logger.getLogger(FaceApi.class);
//人脸分析
public RootResp detectFace(ApiConfiguration config, String url) {
RootResp result = new RootResp();
try{
Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(config.getServerIp());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
JSONObject paramObj = new JSONObject();
paramObj.put("Url", url);
paramObj.put("MaxFaceNum",1);
paramObj.put("MinFaceSize",34);
paramObj.put("NeedFaceAttributes",0);
paramObj.put("NeedQualityDetection",1);
DetectFaceRequest req = DetectFaceRequest.fromJsonString(paramObj.toJSONString(),DetectFaceRequest.class);
DetectFaceResponse resp = client.DetectFace(req);
result.setData(DetectFaceResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
//添加个体
public RootResp newperson(ApiConfiguration config, String personId, String personName, String image) {
RootResp result = new RootResp();
try{
Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(config.getServerIp());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
JSONObject paramObj = new JSONObject();
paramObj.put("GroupId", config.getGroupId());
paramObj.put("PersonId", config.getPersonIdPre() + personId);
paramObj.put("PersonName", personName);
paramObj.put("Image", image);
CreatePersonRequest req = CreatePersonRequest.fromJsonString(paramObj.toJSONString(), CreatePersonRequest.class);
CreatePersonResponse resp = client.CreatePerson(req);
result.setData(CreatePersonResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
//删除个体
public RootResp delperson(ApiConfiguration config, String personId) {
RootResp result = new RootResp();
try{
Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(config.getServerIp());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
JSONObject paramObj = new JSONObject();
paramObj.put("PersonId", config.getPersonIdPre() + personId);
DeletePersonRequest req = DeletePersonRequest.fromJsonString(paramObj.toJSONString(), DeletePersonRequest.class);
DeletePersonResponse resp = client.DeletePerson(req);
result.setData(DeletePersonResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
//增加人脸
public RootResp addface(ApiConfiguration config, String personId, String image) {
RootResp result = new RootResp();
try{
Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(config.getServerIp());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
JSONObject paramObj = new JSONObject();
JSONArray images = new JSONArray();
images.add(image);
paramObj.put("PersonId", config.getPersonIdPre() + personId);
paramObj.put("Images", images);
CreateFaceRequest req = CreateFaceRequest.fromJsonString(paramObj.toJSONString(), CreateFaceRequest.class);
CreateFaceResponse resp = client.CreateFace(req);
result.setData(CreateFaceResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
//删除人脸
public RootResp delface(ApiConfiguration config, String personId, String faceId) {
RootResp result = new RootResp();
try{
Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(config.getServerIp());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
JSONObject paramObj = new JSONObject();
JSONArray faces = new JSONArray();
faces.add(faceId);
paramObj.put("PersonId", config.getPersonIdPre() + personId);
paramObj.put("FaceIds", faces);
DeleteFaceRequest req = DeleteFaceRequest.fromJsonString(paramObj.toJSONString(), DeleteFaceRequest.class);
DeleteFaceResponse resp = client.DeleteFace(req);
result.setData(DeleteFaceResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
//人脸验证
public RootResp faceVerify(ApiConfiguration config, String personId, String image) {
RootResp result = new RootResp();
try{
Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(config.getServerIp());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
JSONObject paramObj = new JSONObject();
paramObj.put("PersonId", config.getPersonIdPre() + personId);
paramObj.put("Image", image);
VerifyFaceRequest req = VerifyFaceRequest.fromJsonString(paramObj.toJSONString(), VerifyFaceRequest.class);
VerifyFaceResponse resp = client.VerifyFace(req);
result.setData(VerifyFaceResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
//人员搜索按库返回
public RootResp searchPersonsReturnsByGroup(ApiConfiguration config, String image) {
RootResp result = new RootResp();
try{
Credential cred = new Credential(config.getSecretId(), config.getSecretKey());
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint(config.getServerIp());
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
IaiClient client = new IaiClient(cred, config.getArea(), clientProfile);
JSONObject paramObj = new JSONObject();
paramObj.put("GroupIds", new String[] {config.getGroupId()});
paramObj.put("Image", image);
//最多返回的最相似人员数目
paramObj.put("MaxPersonNumPerGroup", 5);
//返回人员具体信息
paramObj.put("NeedPersonInfo", 1);
//最多识别的人脸数目
paramObj.put("MaxFaceNum", 1);
SearchFacesReturnsByGroupRequest req = SearchFacesReturnsByGroupRequest.fromJsonString(paramObj.toJSONString(), SearchFacesReturnsByGroupRequest.class);
SearchFacesReturnsByGroupResponse resp = client.SearchFacesReturnsByGroup(req);
result.setData(VerifyFaceResponse.toJsonString(resp));
} catch (TencentCloudSDKException e) {
result.setRet(-1);
result.setMsg(e.toString());
logger.error(e.toString());
}
logger.info(result);
return result;
}
}
我们主要使用newperson()和searchPersonsReturnsByGroup()方法,前者用于人脸采集,把人脸入库;后者用于识别人脸,在进出小区时用到。
结果封装类:
java
package com.qcby.util;
import com.alibaba.fastjson.JSON;
public class RootResp {
private int ret = 0;
public int getRet() {
return this.ret;
}
public void setRet(int ret) {
this.ret = ret;
}
private String msg;
public String getMsg() {
return this.msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
private Object data;
public Object getData() {
return this.data;
}
public void setData(Object data) {
this.data = data;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}
java
package com.qcby.util;
import java.util.HashMap;
public class Result extends HashMap<String,Object> {
public static Result ok(){
Result result = new Result();
result.put("code", 200);
result.put("msg", "操作成功");
return result;
}
public static Result error(String msg){
Result result = new Result();
result.put("code", 500);
result.put("msg", msg);
return result;
}
@Override
public Result put(String key, Object value) {
super.put(key, value);
return this;
}
}
人脸采集接口:
java
/**
* 人脸采集
*
*/
@PostMapping("/addPerson")
public Result addPersonFace(@RequestBody PersonFaceAddForm form){
//程序严谨性判断
Person person = this.personService.getById(form.getPersonId());
if(person == null){
return Result.error("居民不存在");
}
// 检查是否已存在人脸信息
if(person.getFaceUrl() != null && !person.getFaceUrl().isEmpty() && person.getState() == 2) {
return Result.error("该居民已录入人脸信息,无法重复录入");
}
if(person.getState() == 2){
return Result.error("人脸识别已通过,不需要重复识别");
}
if(form.getFileBase64() == null || form.getFileBase64().equals("")){
return Result.error("请上传Base64编码的图片");
}
if(apiConfiguration.isUsed()){
//构建人脸
String faceId = personVal(form,person.getUserName());
if(faceId != null){
//生成头像访问路径
String filename = faceId + "." + form.getExtName();
String faceUrl = urlPrefix + "community/upload/face/" + filename;
person.setState(2);
person.setFaceUrl(faceUrl);
boolean updateResult = personService.updateById(person);
if (!updateResult){
return Result.error("人脸录入失败!");
}
}
}else{
return Result.error("未开启人脸识别接口");
}
return Result.ok();
}
需要调用的方法:
java
/**
* 添加人脸,创建人脸信息并且添加到腾讯云的人脸库
* @param form
* @param userName
* @return
*/
private String personVal(PersonFaceAddForm form,String userName){
String faceId = null;
String faceBase64 = form.getFileBase64();
String extname = form.getExtName();
String personId = form.getPersonId()+"";
//D:/community/upload/face/
String savePath = face;
if (faceBase64!=null && !faceBase64.equals("")) {
FaceApi faceApi = new FaceApi();
RootResp resp = faceApi.newperson(apiConfiguration, personId, userName, faceBase64);
if(resp.getRet()==0) {
JSONObject data = JSON.parseObject(resp.getData().toString());
faceId = data.getString("FaceId");
if(faceId!=null) {
String filename = faceId + "." + extname;
savePath += filename;
try {
Base64Util.decoderBase64File(faceBase64, savePath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
else {
return faceId;
}
}
return faceId;
}
form实体类中封装了这个居民的personId,上传图片的文件拓展名extName,图片的Base64编码fileBase64
接口当中的执行:
(1)严谨性校验
在数据库中查询该居民是否存在,查询这个居民是否已经采集过人脸,检验图片的base64是否合法
(2)构建人脸
在进行完严谨性校验之后,如果启用了人脸识别功能,会调用personVal方法来调用工具类当中的添加人员的方法,执行成功之后会返回这个用户在人员库当中的id
java
String faceId = personVal(form,person.getUserName());
在personVal当中,传入了form,还是那几个属性。
在方法内部首先获取了这三个属性,定义了返回结果faceId=null,获取了文件的保存路径savePath
savePath在配置文件当中配置,通过@Value注解获取值:
java
upload:
face: D:/community/upload/face/
urlPrefix: http://localhost:8282/
excel: D:/community/upload/excel/
java
@Value("${upload.face}")
private String face;
java
String faceId = null;
String faceBase64 = form.getFileBase64();
String extname = form.getExtName();
String personId = form.getPersonId()+"";
//D:/community/upload/face/
String savePath = face;
获取到这些值之后创建了FaceApi对象,准备调用其的newperson方法
java
if (faceBase64!=null && !faceBase64.equals("")) {
FaceApi faceApi = new FaceApi();
RootResp resp = faceApi.newperson(apiConfiguration, personId, userName, faceBase64);
if(resp.getRet()==0) {
JSONObject data = JSON.parseObject(resp.getData().toString());
faceId = data.getString("FaceId");
if(faceId!=null) {
String filename = faceId + "." + extname;
savePath += filename;
try {
Base64Util.decoderBase64File(faceBase64, savePath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
else {
return faceId;
}
}
传入参数后调用方法,如果接口调用无误,resp.getRet()会等于0,接口返回的数据如下:
java
{
"FaceId" : "6618560869116710459",
"FaceRect" : {
"X" : 31,
"Y" : 52,
"Width" : 60,
"Height" : 78
},
"SimilarPersonId" : "",
"FaceModelVersion" : "3.0",
"RequestId" : "b5b6ffe2-93d7-4efb-b333-2df72cc468e7"
}
取出faceId用作上传图片的唯一名字,随后获取到savePath:

java
Base64Util.decoderBase64File(faceBase64, savePath);
这个方法参数传入了Base64 编码的字符串(faceBase64) + 保存路径(savePath),然后将 Base64 解码成二进制数据,保存为文件到指定路径,也就是我的D:/community/upload/face/6618560869116710459.png
返回faceId

(3)更新用户状态,设置图片Url
随后回到接口方法,生成图片的访问路径faceUrl,然后存到数据库中,因为上传的图片和此处生成的图片名字都由faceId拼接,所以能够访问到,urlPrefix和savePath同理,都在yaml配置文件中配置。
java
//构建人脸
String faceId = personVal(form,person.getUserName());
if(faceId != null){
//生成头像访问路径
String filename = faceId + "." + form.getExtName();
String faceUrl = urlPrefix + "community/upload/face/" + filename;
person.setState(2);
person.setFaceUrl(faceUrl);
boolean updateResult = personService.updateById(person);
if (!updateResult){
return Result.error("人脸录入失败!");
}
}
更新完后返回Result.ok()
上传完之后状态变成了已识别,也能看到图片。
