民工心事 发表于 2023-6-9 16:17:31

百度人脸识别_SpringBoot整合离线SDK

一、前言


[*]建议使用低版本 SDK : Baidu_Face_Offline_SDK_Windows_Java_6.1.3

[*]目前已知8.x版本对服务端不兼容,存在运行过程中,第一次调用sdk能够正常执行,第二次时出现JVM异常。
[*]SDK不支持多线程,一般都用于设备端,如人脸闸机上的面板机设备。

[*]自定义库文件路径,与项目分离。
[*]整合springBoot项目,实现启动初始化SDK,按需调用。
二、SDK 引入并配置


[*]解压程序,查看对应操作系统的文件夹,将src目录下的文件移动到我们的项目中。请不要修改此目录结构。
https://note.youdao.com/yws/api/personal/file/WEB59d29d29978878db9d26f17861f89c0b?method=download&shareKey=420407753f8e6fda3ee81f776a1ee105
[*]给Face.java类添加注解,实现条件实例化。
@Slf4j
@Component
@Conditional(FaceSdkEnableCondition.class)
public class Face {
    // *******以下为人脸sdk api接口*********
[*]修改Face.java类加载库的方式,以及初始化。
[*]新增 Environment 类动态获取库路径。
[*]更换 System.load() 加载库文件。
[*]使用 @PostConstruct 注解,当类对象被创建时,自动完成初始化工作。
[*]使用 @PreDestroy 注解,当类对象被销毁时,自动完成释放内存工作。

// ********* 以下为系统加载库文件及opencv **********
    private static String libPath;
    public Face(){ }

    @Autowired
    public Face(Environment env) {
      // 初始化libPath
      libPath = env.getProperty("face-sdk.libPath",String.class);
      // 加载dll文件
      System.load(libPath + "BaiduFaceApi.dll");
      System.load(libPath + "opencv_java320.dll");
    }

    Face api = null;

    /*sdk初始化 */
    @PostConstruct
    public void init() {
      log.info("离线SDK开始初始化");
      log.info("SDK路径:{}",libPath);
      api = new Face();
      int res = api.sdkInit(libPath);
      if (res != 0) {
            log.info("sdk init fail and error = {}\n", res);
            return;
      }
      log.info("离线SDK初始化完成");
    }

    /*sdk释放内存 */
    @PreDestroy
    private void destroy() {
      if(api != null){
            api.sdkDestroy();
      }
      log.info("离线SDK销毁");
    }
[*]配置条件启动类相关
package cn.dyina.config;

public class FaceSdkEnableCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
      Environment env = context.getEnvironment();
      // 根据face-sdk.enable属性来决定是否创建 Face bean
      return "true".equals(env.getProperty("face-sdk.enable"));
    }
}
[*] 配置路径存放库文件
face-sdk:
enable: true
# 路径请务必使用双斜杆
libPath: D:\\FaceLib\\
imagesPath: D:\\FaceImages\\
[*]请将SDK文件的所有.dll文件拷贝到 libPath 目录下。
[*]请将SDK文件下的opencv-jar、models、license文件夹拷贝到libPath 目录下。
[*]请登录 百度智能云 控制中心,注册并获取离线识别SDK序列号,替换license\license.key内的序列号。

[*] 安装maven依赖,以解决打包异常
https://note.youdao.com/yws/api/personal/file/WEB615b69119e431e4c5ba0ddfa20664ef0?method=download&shareKey=420407753f8e6fda3ee81f776a1ee105

[*]请修改并在项目终端执行以下的命令,将opencv-jar下的opencv-320.jar依赖安装到maven仓库。
mvn install:install-file -DgroupId=cn.dyina(jar包的groupId) -DartifactId=opencv-jar(jar包的artifactId) -Dversion=1.0(jar的版本号) -Dpackaging=jar -Dfile=D:\FaceLib\opencv-jar\opencv-320.jar(jar包的具体路径)
[*]添加maven依赖
<dependency>
    <groupId>cn.dyina</groupId>
    <artifactId>opencv-jar</artifactId>
    <version>1.0</version>
</dependency>
三、项目使用


[*]在SpringBoot启动类上,添加包扫描。
@SpringBootApplication(scanBasePackages = {"cn.dyina","com.jni"})
public class SpringBootBaiDuFaceSdkApplication {
    //...
}
[*]编写service、controller。(以下示例代码仅提供参考,请根据自己的业务需求进行编写。)
@Slf4j
@Service
public class FaceService {
    @Value("${face-sdk.imagesPath}")
    String imagesPath;


    public String registerFace(String fileName, String nickName) {
      // 注册人脸图片
      String ip_nickName = fileName.replaceFirst("[.][^.]+$", "");
      // 获取人脸特征值
      Mat mat = Imgcodecs.imread(imagesPath + fileName);
      long matAddr = mat.getNativeObjAddr();
      // 填充人脸信息 后期将从数据库获取
      String userInfo = nickName;
      String userId = ip_nickName.replace(".","");
      String groupId = "Face";
      // 用人脸特征值注册
      JSONObject res = JSONObject.parseObject(Face.userAddByMat(matAddr, userId, groupId, userInfo));
      log.info("user add result is:{}", res);
      return res.getString("msg");
    }


    public String identifyFace(String fileName) {
      // 调用人脸sdkAPI
      Face.loadDbFace();
      Mat mat1 = Imgcodecs.imread(imagesPath + fileName);
      long mat1Addr = mat1.getNativeObjAddr();
      int type = 0;
      // 和人脸库里面的人脸特征值比较(人脸识别)
      JSONObject res = JSONObject.parseObject(Face.identifyWithAllByMat(mat1Addr, type));
      log.info("identify res is:{}", res);
      if (!res.getString("errno").equals("0")) {
            return res.getString("msg");
      }
      // 获取人脸识别信息
      double score = res.getJSONObject("data")
                .getJSONArray("result")
                .getJSONObject(0)
                .getDouble("score");
      String userId = res.getJSONObject("data")
                .getJSONArray("result")
                .getJSONObject(0)
                .getString("user_id");
      if (score > 80) {
            String nickName = userId.split("_");
            return nickName;
      } else {
            log.info("根据图片获取人员信息失败");
            return "Match score is low";
      }
    }

} /**
*人脸识别 页面相关接口
*/
@Slf4j
@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
public class FaceController {

    @Autowired
    private FaceService faceService;

    @Value("${face-sdk.imagesPath}")
    String imagesPath;

    /**
   * 人脸注册
   * @param file
   * @param ip
   * @param nickName
   * @return
   * @throws IOException
   */
    @PostMapping("/faceRegister")
    public R<String> faceRegister(@RequestParam("photo") MultipartFile file,
                                  @RequestParam("ip") String ip,
                                  @RequestParam("nickName") String nickName) throws IOException {

      String photo = Base64.getEncoder().encodeToString(file.getBytes());
      String fileName = ip + "_" + nickName + ".jpg";
      Base64ToImage.saveImage(imagesPath, fileName, photo);
      // 人脸注册
      String res = faceService.registerFace(fileName, nickName);
      if(!res.equals("success")){
            return R.error(res,null);
      }
      return R.success(null);
    }


    /**
   * 检测人脸
   * @param photo
   * @param ip
   * @return
   */
    @PostMapping("/faceDetection")
    public R<String> faceDetection(@RequestParam("photo") String photo, @RequestParam("ip") String ip) {
      String fileName = ip +".jpg"; // 临时存储,用于检测
      Base64ToImage.saveImage(imagesPath, fileName, photo);
      String res = faceService.identifyFace(fileName);
      return R.success(res);
    }



    /**
   * 查询用户组人脸
   * @param groupId
   * @return
   */
    @GetMapping("/getAllFace")
    public R<List> getAllFace(@RequestParam("groupId") String groupId){
      log.info("====>> getAllFace");
      List<String> userIdList = faceService.getAllFace(groupId);
      return R.success(userIdList);
    }
} 后记


[*] com.jni.face包下,除了Face.java类,其他都是示例程序,可以视情况删除。

[*] models 文件夹里的模型可以按情况删除,详细可以查看文档。

[*] 项目启动后,你的控制台应该会收到SDK初始化的信息。并且你的libPath 目录下应该生成db文件夹,人脸数据将存储在这里。(db文件夹将生成在库文件所在目录。删除face.db后,初始化SDK时会自动生成,不需要额外操作。)

[*] 有生产需求的,但设备量不多,可以咸鱼买序列号。(官网最低100个起购)


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: 百度人脸识别_SpringBoot整合离线SDK