package com.whyc.controller;
|
|
import com.arcsoft.face.FaceEngine;
|
import com.arcsoft.face.toolkit.ImageFactory;
|
import com.arcsoft.face.toolkit.ImageInfo;
|
import com.whyc.constant.YamlProperties;
|
import com.whyc.dto.Response;
|
import com.whyc.factory.FaceEngineFactory;
|
import com.whyc.pojo.db_user.UserInf;
|
import com.whyc.service.FaceService;
|
import com.whyc.service.UserInfService;
|
import com.whyc.util.ActionUtil;
|
import com.whyc.util.CommonUtil;
|
import com.whyc.util.FaceIdentifyUtil;
|
import io.swagger.annotations.Api;
|
import io.swagger.annotations.ApiOperation;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.boot.system.ApplicationHome;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.web.bind.annotation.*;
|
import sun.misc.BASE64Decoder;
|
|
import javax.annotation.Resource;
|
import javax.servlet.ServletContext;
|
import javax.servlet.http.HttpServletRequest;
|
import java.io.File;
|
import java.io.FileOutputStream;
|
import java.io.IOException;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* 人脸识别
|
*/
|
@RequestMapping("face")
|
@RestController
|
@Api(tags = "用户管理-人脸识别")
|
public class FaceController {
|
|
@Resource
|
private FaceService service;
|
|
@Resource
|
private UserInfService userService;
|
|
//@Resource
|
//private MapOutlineService mapOutlineService;
|
|
|
@GetMapping("activeOnline")
|
@ApiOperation(value = "在线激活人脸识别引擎",notes = "只需要刚开始时调用一次,会导致appId与硬件设备绑定,必须有外部网络,否则激活会失败!" +
|
"后续使用无需再调用激活,可以离线使用")
|
public Response activeOnline(){
|
boolean b = FaceIdentifyUtil.active(1);
|
if(b){
|
return new Response().set(1,true,"引擎激活成功");
|
}else{
|
return new Response().set(1,false,"引擎激活失败,请检查网络是否为外网并确认appId和key是否正确!");
|
}
|
}
|
|
@GetMapping("activeOffline")
|
@ApiOperation(value = "离线激活人脸识别引擎,增值版使用")
|
public Response activeOffline(){
|
boolean b = FaceIdentifyUtil.active(2);
|
if(b){
|
return new Response().set(1,true,"引擎激活成功");
|
}else{
|
return new Response().set(1,false,"引擎激活失败,请检查网络是否为外网并确认appId和key是否正确!");
|
}
|
}
|
|
@PostMapping
|
@ApiOperation(value = "添加",notes = "添加到人脸库")
|
public Response add(@RequestBody Map<String,Object> paramMap ){
|
String fileData = (String) paramMap.get("fileData");
|
String uName = (String) paramMap.get("uName");
|
//过滤 uName的特殊字符,避免路径遍历攻击
|
uName = ActionUtil.filterFileName(uName);
|
Integer uId = Integer.parseInt((String)paramMap.get("uId"));
|
//传参 uId,uName,fileData--文件流
|
fileData = fileData.replaceAll(" ", "+");
|
|
//由于图片字符串是由base64编码的,解码成字节数组
|
//data:image/jpeg;base64,
|
// fileData = fileData.replaceAll("data:image/jpeg;base64,","");
|
fileData = fileData.split(",")[1];
|
BASE64Decoder decoder = new BASE64Decoder();
|
byte[] dataBytes = new byte[0];
|
try {
|
dataBytes = decoder.decodeBuffer(fileData);
|
/*for (int i = 0; i < dataBytes.length; ++i) {
|
if (dataBytes[i] < 0) {// 调整异常数据
|
dataBytes[i] += 256;
|
}
|
}*/
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
|
/*=========检查图片是否有效=======*/
|
//检验图片是否有效
|
ImageInfo imageInfo = ImageFactory.getRGBData(dataBytes);
|
//初始化引擎
|
// FaceEngine faceEngine = FaceIdentifyUtil.init();
|
FaceEngine faceEngine = FaceEngineFactory.getInstance();
|
if (faceEngine==null){
|
return new Response().set(1,false,"初始化引擎失败");
|
}else {
|
//检查角度是否端正,检查人脸像素大小是否>50×50
|
Response checkRes1 = FaceIdentifyUtil.orientAndPxDetect(faceEngine,imageInfo);
|
if((boolean)checkRes1.getData()){
|
/*=========图片保存===========*/
|
ApplicationHome applicationHome = new ApplicationHome(getClass());
|
File jarFile = applicationHome.getDir();
|
|
//存储人脸图片的文件夹
|
String fileDirName;
|
if(YamlProperties.runModel == 1) {
|
fileDirName = jarFile.getParentFile().toString() + File.separator + "fg_photo";
|
}else{
|
fileDirName = jarFile.toString() + File.separator + "fg_photo";
|
}
|
|
File file = new File(fileDirName);
|
//不存在则创建该文件夹
|
if (!file.exists()) {
|
file.mkdirs();
|
}
|
|
//文件全路径
|
String fileName = fileDirName + File.separator + uName + ".jpg";
|
FileOutputStream fot=null;
|
try {
|
fot = new FileOutputStream(fileName);
|
fot.write(dataBytes);
|
fot.flush();
|
|
} catch (IOException e) {
|
e.printStackTrace();
|
}finally {
|
if(fot!=null){
|
try {
|
fot.close();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
|
/*=========数据库表更新===========*/
|
// model = service.add(uId, uName, projectName);
|
service.add(uId, uName, fileName);
|
|
return new Response().set(1,true,"新增成功");
|
}
|
return checkRes1;
|
}
|
|
}
|
|
/**
|
* 人脸库管理: 更新
|
* @return
|
*/
|
@PostMapping("update")
|
@ApiOperation(value = "更新")
|
public Response update(@RequestBody String fileData,@RequestParam String uName){
|
//传参,uName,fileData--文件流
|
|
//过滤 uName的特殊字符,避免路径遍历攻击
|
uName = ActionUtil.filterFileName(uName);
|
//由于图片字符串是由base64编码的,解码成字节数组
|
fileData = fileData.replaceAll(" ", "+");
|
fileData = fileData.split(",")[1];
|
BASE64Decoder decoder = new BASE64Decoder();
|
byte[] dataBytes = new byte[0];
|
try {
|
dataBytes = decoder.decodeBuffer(fileData);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
|
/*=========检查图片是否有效=======*/
|
//检验图片是否有效
|
//获取图像信息
|
ImageInfo imageInfo = ImageFactory.getRGBData(dataBytes);
|
//初始化引擎
|
// FaceEngine faceEngine = FaceIdentifyUtil.init();
|
FaceEngine faceEngine = FaceEngineFactory.getInstance();
|
if (faceEngine==null){
|
return new Response().set(1,false,"初始化引擎失败");
|
}else {
|
//检测图片
|
Response checkRes1 = FaceIdentifyUtil.orientAndPxDetect(faceEngine, imageInfo);
|
if ((boolean)checkRes1.getData()) {
|
/*=========图片保存===========*/
|
ApplicationHome applicationHome = new ApplicationHome(getClass());
|
File jarFile = applicationHome.getDir();
|
|
//存储人脸图片的文件夹
|
String fileDirName;
|
if(YamlProperties.runModel == 1) {
|
fileDirName = jarFile.getParentFile().toString() + File.separator + "fg_photo";
|
}else{
|
fileDirName = jarFile.toString() + File.separator + "fg_photo";
|
}
|
|
File file = new File(fileDirName);
|
//不存在则创建该文件夹
|
if (!file.exists()) {
|
file.mkdirs();
|
}
|
|
//文件全路径
|
String fileName = fileDirName + File.separator + uName + ".jpg";
|
FileOutputStream fot =null;
|
try {
|
fot = new FileOutputStream(fileName);
|
fot.write(dataBytes);
|
fot.flush();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}finally {
|
if(fot!=null){
|
try {
|
fot.close();
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
}
|
}
|
return new Response().set(1,"更新成功");
|
}
|
return checkRes1;
|
}
|
}
|
|
/**
|
* 人脸库管理: 删除
|
* @return
|
*/
|
@PostMapping("delete")
|
@ApiOperation(value = "删除")
|
@Transactional
|
public Response delete(@RequestParam Integer uId,@RequestParam Integer faceId,
|
@RequestParam String uName,HttpServletRequest request){
|
|
//过滤 uName的特殊字符,避免路径遍历攻击
|
uName = ActionUtil.filterFileName(uName);
|
//更新user_inf和face表
|
service.update(uId,faceId);
|
|
//删除图片
|
//获取到图片所在文件夹的全路径
|
String fileName = findFileDirPath(request);
|
//获取图片的全路径
|
File file = new File(fileName+File.separator+uName+".jpg");
|
if(file.exists()){
|
file.delete();
|
}
|
|
return new Response().set(1,"删除成功");
|
}
|
|
/**获取图片文件夹全路径
|
* @param request*/
|
private String findFileDirPath(HttpServletRequest request) {
|
ApplicationHome applicationHome = new ApplicationHome(getClass());
|
File jarFile = applicationHome.getDir();
|
//在jar包所在目录下生成一个upload文件夹用来存储上传的图片
|
return jarFile.getParentFile().toString()+File.separator+"fg_photo";
|
}
|
|
/**获取图片的http加载url*/
|
private String findWebPhotoUrl(String uName){
|
HttpServletRequest request = ActionUtil.getRequest();
|
//获取项目名称
|
String realPath = ActionUtil.getApplication().getRealPath("/");
|
//String[] split = realPath.split("/");
|
String[] split = realPath.split(File.separator);
|
String projectName = split[split.length - 1];
|
//图片保存路径,采取ip+port访问形式而非硬盘形式,方便图片加载
|
String url = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+"/"+projectName+"_photo/"+uName+".jpg";
|
return url;
|
}
|
|
/**
|
* 人脸库管理: 查询分页列表
|
* 现在逻辑是当前用户查询自己的人脸信息
|
* @return
|
*/
|
@GetMapping("info")
|
@ApiOperation(value = "查询人脸信息")
|
public Response getInfo(HttpServletRequest request){
|
//传入pageNum,pageSize
|
UserInf userInf = (UserInf) request.getSession().getAttribute("user");
|
UserInf user = service.getInfo(userInf.getUid());
|
|
return new Response().set(1,user);
|
}
|
|
/**
|
* 人脸识别: 活体检验,相似度对比,1比N
|
*/
|
@PostMapping("faceCompare2N")
|
@ApiOperation(value = "人脸识别对比")
|
public Response faceCompare2N(@RequestBody String fileData,@RequestParam String uKeyId,HttpServletRequest request){
|
Response res = new Response();
|
//先验证uKeyId对应的用户
|
UserInf userByUKeyId = userService.getUserByUKeyId(uKeyId);
|
if (userByUKeyId == null){
|
return res.set(1,false,"Ukey没有绑定用户");
|
}
|
|
/*====获取图片并校验活体,角度,像素大小====*/
|
//由于图片字符串是由base64编码的,解码成字节数组
|
fileData = fileData.replaceAll(" ", "+");
|
fileData = fileData.split(",")[1];
|
BASE64Decoder decoder = new BASE64Decoder();
|
byte[] dataBytes = new byte[0];
|
try {
|
dataBytes = decoder.decodeBuffer(fileData);
|
} catch (IOException e) {
|
e.printStackTrace();
|
}
|
ImageInfo imageInfo = ImageFactory.getRGBData(dataBytes);
|
FaceEngine faceEngine = FaceEngineFactory.getInstance();
|
if(faceEngine!=null) {
|
res = FaceIdentifyUtil.liveDetect(faceEngine, imageInfo);
|
//活体校验通过
|
if (res.getCode() == 1) {
|
res = FaceIdentifyUtil.orientAndPxDetect(faceEngine, imageInfo);
|
//人像角度,大小校验通过
|
if((boolean) res.getData()) {
|
//重置标识
|
res.setData(null);
|
res.setMsg(null);
|
//获取数据库中所有的人脸图片
|
List<UserInf> userInfList = service.findAllFaceUrl();
|
if(userInfList.size()==0){
|
res.setCode(0);
|
res.setMsg("人脸库暂无任何数据");
|
}else{
|
boolean urlExist = false;
|
for (UserInf temp:userInfList){
|
String filePath = temp.getFace().getUrl();
|
File file = new File(filePath);
|
//不存在则不继续执行
|
if(!file.exists()){
|
continue;
|
}else{
|
urlExist = true;
|
}
|
ImageInfo imageInfo2 = ImageFactory.getRGBData(file);
|
res = FaceIdentifyUtil.faceCompare(faceEngine, imageInfo, imageInfo2);
|
//对比成功,记录用户登录信息
|
if((boolean) res.getData()){
|
//Ukey对应用户和人脸对应用户验证
|
if(!(temp.getUid()==userByUKeyId.getUid())){
|
return res.set(1,false,"UKey对应用户和当前人脸对应用户不匹配");
|
}
|
List<Object> dataList = new ArrayList<>();
|
dataList.add(temp);
|
|
// 将登陆成功的用户存入session
|
ServletContext servletContext = request.getServletContext();
|
servletContext.setAttribute(temp.getUname(), request.getSession().getId());
|
ActionUtil.getSession().setAttribute("user", temp);
|
|
//设置session不活动时间为30分
|
ActionUtil.getSession().setMaxInactiveInterval(60 * 30);
|
ActionUtil.getSession().setAttribute("ip", ActionUtil.getRequest().getRemoteAddr());
|
/* List<PermitGroup> permitList = permitGroupUserService.getPermitByUser(temp.getUId());
|
if (permitList!=null && permitList.size()!=0) {
|
dataList.add(permitList.get(0).getPermitGroupId());
|
ActionUtil.getSession().setAttribute("permits", permitList);
|
} else {
|
res.setCode(1);
|
res.setData(false);
|
res.setMsg("还未分配权限");
|
}
|
*/
|
//查询用户对应的班组标识
|
//dataList.add(baoJiGroupUserService.getGroupFlag(temp.getUId().intValue()));
|
//查询激活的地图
|
//String mapName = mapOutlineService.selectMapName();
|
//dataList.add(mapName);
|
//CommonUtil.record(temp.getUId(), UserOperation.TYPE_LOGIN.getType(), UserOperation.TYPE_LOGIN.getTypeName(), UserOperation.TYPE_LOGIN.getTypeNameEn());
|
res.setData2(dataList);
|
|
//将新登录的用户存入application
|
userService.setApplication(temp);
|
}
|
}
|
if(!urlExist){
|
res.set(1,false,"ukey对应的人脸库路径不存在");
|
}
|
}
|
}
|
}
|
}else{
|
res.setCode(0);
|
res.setMsg("初始化引擎失败");
|
}
|
|
return res;
|
}
|
|
}
|