whyczh
2021-12-08 3f68c6a5a9968cbfd955e958742d38e5ded682c5
src/main/java/com/whyc/controller/FaceController.java
@@ -1,16 +1,343 @@
package com.whyc.controller;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import com.whyc.dto.Response;
import com.whyc.factory.FaceEngineFactory;
import com.whyc.pojo.PermitGroup;
import com.whyc.pojo.UserInf;
import com.whyc.service.FaceService;
import com.whyc.service.PermitGroupUserService;
import com.whyc.service.UserService;
import com.whyc.util.ActionUtil;
import com.whyc.util.FaceIdentifyUtil;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.ApiOperation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import sun.misc.BASE64Decoder;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import static com.whyc.util.ActionUtil.getApplication;
/**
 * 人脸识别
 */
@RequestMapping("face")
@RestController
@Api(tags = "人脸识别")
@Api(tags = "用户管理-人脸识别")
public class FaceController {
    @Resource
    private FaceService service;
    @Resource
    private PermitGroupUserService permitGroupUserService;
    @Resource
    private UserService userService;
    @GetMapping("activeOnline")
    @ApiOperation(value = "在线激活人脸识别引擎",notes = "只需要刚开始时调用一次,会导致appId与硬件设备绑定,必须有外部网络,否则激活会失败!" +
            "后续使用无需再调用激活,可以离线使用")
    public Response activeOnline(){
        Response model = new Response();
        boolean b = FaceIdentifyUtil.activeOnline();
        if(b){
            return new Response().set(1,true,"引擎激活成功");
        }else{
            return new Response().set(1,false,"引擎激活失败,请检查网络是否为外网并确认appId和key是否正确!");
        }
    }
    @PostMapping
    @ApiOperation(value = "添加",notes = "添加到人脸库")
    public Response add(@RequestParam String fileData,String uName,Integer 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()){
                /*=========图片保存===========*/
                //获取到tomcat webapp绝对路径
                String realPath = getApplication().getRealPath("/");
                String[] split = realPath.split(File.separator);
                //String[] split = realPath.split("\\\\");
                String projectName = split[split.length - 1];
                String webAppPath = realPath.substring(0, realPath.lastIndexOf(projectName));
                //存储人脸图片的文件夹
                String fileDirName = webAppPath + projectName + "_photo";
                File file = new File(fileDirName);
                //不存在则创建该文件夹
                if (!file.exists()) {
                    file.mkdirs();
                }
                //文件全路径
                String fileName = fileDirName + File.separator + uName + ".jpg";
                try {
                    FileOutputStream fot = new FileOutputStream(fileName);
                    fot.write(dataBytes);
                    fot.flush();
                    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
     */
    @PutMapping
    @ApiOperation(value = "更新")
    public Response update(@RequestParam String fileData,String uName){
        //传参,uName,fileData--文件流
        //由于图片字符串是由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()) {
                /*=========图片保存===========*/
                //获取到tomcat webapp绝对路径
                String realPath = getApplication().getRealPath("/");
                String[] split = realPath.split(File.separator);
                String projectName = split[split.length - 1];
                String webAppPath = realPath.substring(0, realPath.lastIndexOf(projectName));
                //存储人脸图片的文件夹
                String fileDirName = webAppPath + projectName + "_photo";
                File file = new File(fileDirName);
                //不存在则创建该文件夹
                if (!file.exists()) {
                    file.mkdirs();
                }
                //文件全路径
                String fileName = fileDirName + File.separator + uName + ".jpg";
                try {
                    FileOutputStream fot = new FileOutputStream(fileName);
                    fot.write(dataBytes);
                    fot.flush();
                    fot.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return new Response().setII(1,"更新成功");
            }
            return checkRes1;
        }
    }
    /**
     * 人脸库管理: 删除
     * @return
     */
    @DeleteMapping
    @ApiOperation(value = "删除")
    @Transactional
    public Response delete(@RequestParam Integer uId,@RequestParam Integer faceId,
                         @RequestParam String uName){
        //更新user_inf和face表
        service.update(uId,faceId);
        //删除图片
        //获取到图片所在文件夹的全路径
        String fileName = findFileDirPath();
        //获取图片的全路径
        File file = new File(fileName+File.separator+uName+".jpg");
        if(file.exists()){
            file.delete();
        }
        return new Response().setII(1,"删除成功");
    }
    /**获取图片文件夹全路径*/
    private String findFileDirPath() {
        String realPath = getApplication().getRealPath("/");
        //String[] split = realPath.split("\\\\");
        String[] split = realPath.split(File.separator);
        String projectName = split[split.length - 1];
        String webAppPath = realPath.substring(0, realPath.lastIndexOf(projectName));
        //存储人脸图片的文件夹
        //String fileDirName = webAppPath + "\\" + projectName + "_photo";
        String fileDirName = webAppPath + File.separator + projectName + "_photo";
        return fileDirName;
    }
    /**获取图片的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(){
        //传入pageNum,pageSize
        UserInf userInf = (UserInf) ActionUtil.getSession().getAttribute("user");
        UserInf user = service.getInfo(userInf.getUId());
        return new Response().set(1,user);
    }
    /**
     * 人脸识别: 活体检验,相似度对比,1比N
     */
    @PostMapping("faceCompare2N")
    @ApiOperation(value = "人脸识别对比")
    public Response faceCompare2N(@RequestParam String fileData){
        Response res = new Response();
        /*====获取图片并校验活体,角度,像素大小====*/
        //由于图片字符串是由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(res.getCode()==1) {
                    //获取数据库中所有的人脸图片
                    List<UserInf> userInfList = service.findAllFaceUrl();
                    if(userInfList.size()==0){
                        res.setCode(0);
                        res.setMsg("人脸库暂无任何数据");
                    }else{
                        for (UserInf temp:userInfList){
                            String filePath = temp.getFace().getUrl();
                            ImageInfo imageInfo2 = ImageFactory.getRGBData(new File(filePath));
                            Response res3 = FaceIdentifyUtil.faceCompare(faceEngine, imageInfo, imageInfo2);
                            //对比成功,记录用户登录信息
                            if(res3.getCode()==1){
                                // 将登陆成功的用户存入session
                                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) {
                                    ActionUtil.getSession().setAttribute("permits", permitList);
                                } else {
                                    res.setCode(0);
                                    res.setMsg("还未分配权限");
                                }
                                //将新登录的用户存入application
                                userService.setApplication(temp);
                            }
                        }
                    }
                }
            }
        }else{
            res.setCode(0);
            res.setMsg("初始化引擎失败");
        }
        return res;
    }
}