人脸识别开发demo

开发前准备:

开发使用到的软件和工具:
Jdk8(64位,Oracle版本)、mysql5.73、spring boot、mybatis
{libarcsoft_face.dll(so)、libarcsoft_face_engine.dll(so)、libarcsoft_face_engine_jni.dll(so)}这些可以去官网下载。
其中里面的配置文件路径,io文件路径需要修改

数据表的配置

在这里插入图片描述

部分代码展示

  • sprinh boot启动器
package com.facedemo;
@SpringBootApplication
@MapperScan({"com.gxd.facedemo.dao.mapper","com.gxd.facedemo.mapper"})
@EnableTransactionManagement
@EnableSwagger2Doc
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
  • 配置文件设置
config.arcface-sdk.app-id=91BifrT9RHbUENePMKBKpCVv8TivpeUsViUwcREygaw1
# win
# config.arcface-sdk.sdk-lib-path=C:/facelib
# config.arcface-sdk.sdk-# key=7HSLAwHDNQy8XyVaqjjBxERtmfZA5btoqhmNGQEYSo8Y
# linux
config.arcface-sdk.sdk-lib-path=/usr/lib64
config.arcface-sdk.sdk-key=7HSLAwHDNQy8XyVaqjjBxERtdYz3QzutFqyRXsdMHRrj
config.arcface-sdk.thread-pool-size=5

注意 :此处建议修改为自己的文件路径,此处仅从参考!

核心类

人脸添加

package com.gxd.facedemo.controller;


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollectionUtil;
import com.arcsoft.face.toolkit.ImageFactory;
import com.arcsoft.face.toolkit.ImageInfo;
import com.gxd.facedemo.base.Result;
import com.gxd.facedemo.base.Results;
import com.gxd.facedemo.domain.UserFaceInfo;
import com.gxd.facedemo.dto.FaceCompareResDto;
import com.gxd.facedemo.dto.FaceSearchResDto;
import com.gxd.facedemo.dto.FaceUserInfo;
import com.gxd.facedemo.dto.ProcessInfo;
import com.gxd.facedemo.enums.ErrorCodeEnum;
import com.gxd.facedemo.request.FaceCompareRequest;
import com.gxd.facedemo.service.UserFaceInfoService;
import com.gxd.facedemo.service.FaceEngineService;
import com.arcsoft.face.FaceInfo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.Base64Utils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;
import java.util.UUID;

import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
@Api(tags={"人脸相关"})
@Controller
public class FaceController {

    public final static Logger logger = LoggerFactory.getLogger(FaceController.class);


    @Autowired
    FaceEngineService faceEngineService;

    @Autowired
    UserFaceInfoService userFaceInfoService;

    @ApiIgnore
    @RequestMapping(value = "/demo")
    public String demo() {
        return "demo";
    }
    /**
     * 人脸添加
     */
    @ApiOperation(value="人脸添加", notes="添加人脸,人脸图片为base64格式字符串")
    @RequestMapping(value = "/faceAdd", method = RequestMethod.POST)
    @ResponseBody
    public Result<Object> faceAdd(@ApiParam(value = "人脸图像数据", required = true) @RequestParam("file") String file, @ApiParam(value = "分组id", required = true)@RequestParam("groupId") Integer groupId, @ApiParam(value = "人脸姓名", required = true)@RequestParam("name") String name) {
        try {
            if (file == null) {
                return Results.newFailedResult("人脸照片不能为空");
            }
            if (groupId == null) {
                return Results.newFailedResult("分组id不能为空");
            }
            if (name == null) {
                return Results.newFailedResult("姓名不能为空");
            }

            byte[] decode = Base64.decode(base64Process(file));
            ImageInfo imageInfo = getRGBData(decode);

            //人脸特征获取
            byte[] bytes = faceEngineService.extractFaceFeature(imageInfo);
            if (bytes == null) {
                return Results.newFailedResult(ErrorCodeEnum.NO_FACE_DETECTED);
            }
            UserFaceInfo userFaceInfo = new UserFaceInfo();
            userFaceInfo.setFaceId(UUID.randomUUID().toString().replace("-","").substring(0,10));
            userFaceInfo.setName(name);
            userFaceInfo.setGroupId(groupId);
            userFaceInfo.setFaceFeature(bytes);

            //人脸特征插入到数据库
            userFaceInfoService.insertSelective(userFaceInfo);

            logger.info("faceAdd:" + name);
            return Results.newSuccessResult("");
        } catch (Exception e) {
            logger.error("", e);
        }
        return Results.newFailedResult(ErrorCodeEnum.UNKNOWN);
    }

    /**
     * 人脸识别
     */
    @ApiOperation(value="人脸识别", notes="待识别图像为base64格式字符串、必须指定人脸分组id")
    @RequestMapping(value = "/faceSearch", method = RequestMethod.POST)
    @ResponseBody
    public Result<FaceSearchResDto> faceSearch(@ApiParam(value = "人脸图像数据", required = true)@RequestParam("file")   String file, @ApiParam(value = "分组id", required = true) @RequestParam("groupId") Integer groupId) throws Exception {

        if (groupId == null) {
            return Results.newFailedResult("groupId is null");
        }
        byte[] decode = Base64.decode(base64Process(file));
        BufferedImage bufImage = ImageIO.read(new ByteArrayInputStream(decode));
        ImageInfo imageInfo = ImageFactory.bufferedImage2ImageInfo(bufImage);


        //人脸特征获取
        byte[] bytes = faceEngineService.extractFaceFeature(imageInfo);
        if (bytes == null) {
            return Results.newFailedResult(ErrorCodeEnum.NO_FACE_DETECTED);
        }
        //人脸比对,获取比对结果
        List<FaceUserInfo> userFaceInfoList = faceEngineService.compareFaceFeature(bytes, groupId);

        if (CollectionUtil.isNotEmpty(userFaceInfoList)) {
            FaceUserInfo faceUserInfo = userFaceInfoList.get(0);
            FaceSearchResDto faceSearchResDto = new FaceSearchResDto();
            BeanUtil.copyProperties(faceUserInfo, faceSearchResDto);
            List<ProcessInfo> processInfoList = faceEngineService.process(imageInfo);
            if (CollectionUtil.isNotEmpty(processInfoList)) {
                //人脸检测
                List<FaceInfo> faceInfoList = faceEngineService.detectFaces(imageInfo);
                int left = faceInfoList.get(0).getRect().getLeft();
                int top = faceInfoList.get(0).getRect().getTop();
                int width = faceInfoList.get(0).getRect().getRight() - left;
                int height = faceInfoList.get(0).getRect().getBottom() - top;

                Graphics2D graphics2D = bufImage.createGraphics();
                graphics2D.setColor(Color.RED);//红色
                BasicStroke stroke = new BasicStroke(5f);
                graphics2D.setStroke(stroke);
                graphics2D.drawRect(left, top, width, height);
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                ImageIO.write(bufImage, "jpg", outputStream);
                byte[] bytes1 = outputStream.toByteArray();
                faceSearchResDto.setImage("data:image/jpeg;base64," + Base64Utils.encodeToString(bytes1));
                faceSearchResDto.setAge(processInfoList.get(0).getAge());
                faceSearchResDto.setGender(processInfoList.get(0).getGender().equals(1) ? "女" : "男");

            }

            return Results.newSuccessResult(faceSearchResDto);
        }
        return Results.newFailedResult(ErrorCodeEnum.FACE_DOES_NOT_MATCH);
    }

    /**
     * 人脸对比
     */
    @RequestMapping(value = "/faceCompare", method = RequestMethod.POST)
    @ResponseBody
    @ApiOperation(value="人脸对比", notes="待识别图像为base64格式字符串")
    public Result<FaceCompareResDto> faceCompare(@RequestBody FaceCompareRequest request) throws Exception{

        // 已知人脸
        byte[] decode1 = Base64.decode(base64Process(request.getFileKnown()));
        BufferedImage bufImage1 = ImageIO.read(new ByteArrayInputStream(decode1));
        ImageInfo imageInfo1 = ImageFactory.bufferedImage2ImageInfo(bufImage1);
        //人脸1特征获取
        byte[] bytes1 = faceEngineService.extractFaceFeature(imageInfo1);

        // 未知人脸
        byte[] decode2 = Base64.decode(base64Process(request.getFileUnknown()));
        BufferedImage bufImage2 = ImageIO.read(new ByteArrayInputStream(decode2));
        ImageInfo imageInfo2 = ImageFactory.bufferedImage2ImageInfo(bufImage2);
        //人脸2特征获取
        byte[] bytes2 = faceEngineService.extractFaceFeature(imageInfo2);
        // 人脸对比
        FaceCompareResDto res = faceEngineService.compareFaces(bytes1,bytes2);

        return Results.newSuccessResult(res);
    }

    private String base64Process(String base64Str) {
        if (!StringUtils.isEmpty(base64Str)) {
            String photoBase64 = base64Str.substring(0, 30).toLowerCase();
            int indexOf = photoBase64.indexOf("base64,");
            if (indexOf > 0) {
                base64Str = base64Str.substring(indexOf + 7);
            }

            return base64Str;
        } else {
            return "";
        }
    }
}

人脸删除

package com.gxd.facedemo.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gxd.facedemo.base.Result;
import com.gxd.facedemo.base.Results;
import com.gxd.facedemo.domain.UserFaceInfo;
import com.gxd.facedemo.mapper.MybatisUserFaceInfoMapper;
import com.gxd.facedemo.request.DeleteFaceRequest;
import com.gxd.facedemo.service.UserFaceInfoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;

@Api(tags={"数据维护"})
@RestController
public class UserListController {

    @Autowired
    MybatisUserFaceInfoMapper userFaceInfoMapper;

    @Autowired
    private UserFaceInfoService userFaceInfoService;


    @ApiOperation(value="获取所有人脸数据")
    @GetMapping("/userInfo")
    public List<UserFaceInfo> getUserInfo()
    {
        List<UserFaceInfo> list = new ArrayList<UserFaceInfo>();
        list = userFaceInfoMapper.findUserFaceInfoList();
        return list;
    }
    /**
     * 根据分组id和名称删除人脸
     */
    @ResponseBody
    @PostMapping("/deleteFaceByName")
    @ApiOperation(value="根据分组id和名称删除人脸")
    public Result<Object> deleteFaceByName(@RequestBody DeleteFaceRequest request) {
        if ("".equals(request.getName())) {
            return Results.newFailedResult("姓名不能为空");
        }
        if (request.getGroupId() == null) {
            return Results.newFailedResult("分组id不能为空");
        }
        List<UserFaceInfo> userList = userFaceInfoService.list(new QueryWrapper<UserFaceInfo>().eq("group_id", request.getGroupId()).eq("name", request.getName()));
        if (userList==null||userList.isEmpty()){
            return Results.newFailedResult("人脸数据不存在,删除失败");
        }
        List<Integer> userIdList = new ArrayList<>();
        for (UserFaceInfo userFaceInfo : userList) {
            userIdList.add(userFaceInfo.getId());
        }
        userFaceInfoService.removeByIds(userIdList);
        return Results.newSuccessResult("删除人脸数据成功");
    }

    /**
     * 删除人脸集合
     */
    @ResponseBody
    @PostMapping("/deleteFaceSet/{groupId}")
    @ApiOperation(value="删除人脸集合")
    public Result<Object> deleteFaceSet(@PathVariable("groupId") Integer groupId) {
        if (groupId == null) {
            return Results.newFailedResult("分组id不能为空");
        }
        int num = userFaceInfoService.count(new QueryWrapper<UserFaceInfo>().eq("group_id",groupId));
        if (num == 0){
            return Results.newFailedResult("当前集合不存在");
        }
        userFaceInfoService.remove(new QueryWrapper<UserFaceInfo>().eq("group_id",groupId));
        return Results.newSuccessResult("删除人脸集合成功");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

啊~小 l i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值