Kaynağa Gözat

人脸识别服务代码整合

hecheng 3 yıl önce
ebeveyn
işleme
39d203cdb1

+ 120 - 11
zd-modules/zd-algorithm/src/main/java/com/zd/alg/face/handle/FaceEngineFactory.java

@@ -8,18 +8,24 @@ import com.arcsoft.face.FunctionConfiguration;
 import com.arcsoft.face.enums.DetectMode;
 import com.arcsoft.face.enums.DetectOrient;
 import com.arcsoft.face.enums.ErrorInfo;
-import com.zd.common.core.exception.ServiceException;
 import com.zd.alg.face.config.FaceProperties;
+import com.zd.common.core.exception.ServiceException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
+import org.springframework.core.io.ClassPathResource;
 import org.springframework.core.io.FileSystemResource;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.rmi.ServerException;
+import java.util.LinkedList;
+import java.util.List;
 
 /**
  * @Author: zhoupan
@@ -37,8 +43,16 @@ public class FaceEngineFactory {
     @Autowired
     EngineConfiguration getEngineConfiguration;
 
+    private static String PLATFORM;
+
+    private static final String USER_HOME;
+
+    public static String CACHE_LIB_FOLDER;
+
+    public String ARC_FACE_VERSION = "3.0";
+
     //初始化一个图片模式引擎
-    public FaceEngine initFaceEngineImage() {
+    public FaceEngine initFaceEngineImage() throws IOException {
         //初始化IMAGE模式
         return init();
     }
@@ -71,13 +85,108 @@ public class FaceEngineFactory {
         }
     }
 
+    static {
+        String jvmName = System.getProperty("java.vm.name", "").toLowerCase();
+        String osName = System.getProperty("os.name", "").toLowerCase();
+        String osArch = System.getProperty("os.arch", "").toLowerCase();
+        String abiType = System.getProperty("sun.arch.abi", "").toLowerCase();
+        String libPath = System.getProperty("sun.boot.library.path", "").toLowerCase();
+        USER_HOME = System.getProperty("user.home");
+        if (jvmName.startsWith("dalvik") && osName.startsWith("linux")) {
+            osName = "android";
+        } else if (jvmName.startsWith("robovm") && osName.startsWith("darwin")) {
+            osName = "ios";
+            osArch = "arm";
+        } else if (osName.startsWith("mac os x") || osName.startsWith("darwin")) {
+            osName = "macosx";
+        } else {
+            int spaceIndex = osName.indexOf(' ');
+            if (spaceIndex > 0) {
+                osName = osName.substring(0, spaceIndex);
+            }
+        }
+        if (osArch.equals("i386") || osArch.equals("i486") || osArch.equals("i586") || osArch.equals("i686")) {
+            osArch = "x86";
+        } else if (osArch.equals("amd64") || osArch.equals("x86-64") || osArch.equals("x64")) {
+            osArch = "x86_64";
+        } else if (osArch.startsWith("aarch64") || osArch.startsWith("armv8") || osArch.startsWith("arm64")) {
+            osArch = "arm64";
+        } else if ((osArch.startsWith("arm")) && ((abiType.equals("gnueabihf")) || (libPath.contains("openjdk-armhf")))) {
+            osArch = "armhf";
+        } else if (osArch.startsWith("arm")) {
+            osArch = "arm";
+        }
+        PLATFORM = osName + "-" + osArch;
+
+    }
+
+    public void afterPropertiesSet() throws IOException {
+        CACHE_LIB_FOLDER = USER_HOME + "/.arcface/cache/" + ARC_FACE_VERSION + "/" + PLATFORM + "/";
+        loadLibrary();
+    }
+
+    public void loadLibrary() throws IOException {
+        String baseFolder = "";
+        String suffix = ".dll";
+        if ("windows-x86_64".equals(PLATFORM)) {
+            baseFolder = "WIN64";
+        } else if ("windows-x86".equals(PLATFORM)) {
+            baseFolder = "WIN32";
+        } else if ("linux-x86_64".equals(PLATFORM)) {
+            baseFolder = "LINUX64";
+            suffix = ".so";
+        }
+
+        if ("".equals(baseFolder)) {
+            throw new ServerException("ArcFace不支持该操作系统");
+        }
+
+
+        File file = new File(CACHE_LIB_FOLDER);
+        if (!file.exists()) {
+            file.mkdirs();
+        }
+
+        List<String> libList = new LinkedList<>();
+        libList.add("libarcsoft_face");
+        libList.add("libarcsoft_face_engine");
+        libList.add("libarcsoft_face_engine_jni");
+
+        for (String lib : libList) {
+            ClassPathResource resource = new ClassPathResource("libs/" + ARC_FACE_VERSION + "/" + baseFolder + "/" + lib + suffix);
+            InputStream inputStream = resource.getInputStream();
+            int faceLength = inputStream.available();
+            File facePath = new File(CACHE_LIB_FOLDER + lib + suffix);
+            if (facePath.exists()) {
+                if (facePath.length() == faceLength) {
+                    continue;
+                }
+                facePath.delete();
+            }
+            writeToLocal(CACHE_LIB_FOLDER + lib + suffix, inputStream);
+        }
+    }
+
+    private void writeToLocal(String destination, InputStream input)
+            throws IOException {
+        int index;
+        byte[] bytes = new byte[1024 * 100];
+        FileOutputStream fileOutputStream = new FileOutputStream(destination);
+        while ((index = input.read(bytes)) != -1) {
+            fileOutputStream.write(bytes, 0, index);
+        }
+        fileOutputStream.flush();
+        fileOutputStream.close();
+        input.close();
+    }
+
     public String getPath() throws IOException {
         FileSystemResource resource = new FileSystemResource("../");
         String canonicalPath = resource.getFile().getCanonicalPath();
         if (StrUtil.isNotBlank(faceProperties.getLib_folder())) {
             canonicalPath = canonicalPath + File.separator + faceProperties.getLib_folder();
         }
-        return canonicalPath;
+        return CACHE_LIB_FOLDER;
     }
 
     public void activation(FaceEngine faceEngine) {
@@ -115,16 +224,16 @@ public class FaceEngineFactory {
 
         String canonicalPath = null;
         try {
-            //FaceEngine 里加载sdk的方法已经写死了,没办法从打的jar文件中正确获取文件,
-            // 里面用的System.load方法,没办法通过路径加载jar文件中的文件
-            //所以这里只能把lib文件放在jar文件外部
-            canonicalPath = getPath();
-            logger.info("获取lib文件路径!:{}", canonicalPath);
-            faceEngine = new FaceEngine(canonicalPath);
+            afterPropertiesSet();
         } catch (IOException e) {
-            logger.error("lib文件路径获取失败,引擎初始化中断,请正确配置后激活!当前读取路径:{}", canonicalPath);
-            throw new ServiceException("lib文件加载失败!");
+            throw new RuntimeException(e);
         }
+        //FaceEngine 里加载sdk的方法已经写死了,没办法从打的jar文件中正确获取文件,
+        // 里面用的System.load方法,没办法通过路径加载jar文件中的文件
+        //所以这里只能把lib文件放在jar文件外部
+//            canonicalPath = getPath();
+        logger.info("获取lib文件路径!:{}", CACHE_LIB_FOLDER);
+        faceEngine = new FaceEngine(CACHE_LIB_FOLDER);
         return faceEngine;
     }
 

+ 23 - 19
zd-modules/zd-algorithm/src/main/java/com/zd/alg/face/service/FaceService.java

@@ -6,14 +6,17 @@ import com.arcsoft.face.FaceInfo;
 import com.arcsoft.face.FaceSimilar;
 import com.arcsoft.face.enums.ErrorInfo;
 import com.arcsoft.face.toolkit.ImageInfo;
-import com.zd.common.core.utils.Assert;
 import com.zd.alg.face.config.FaceProperties;
 import com.zd.alg.face.handle.FaceEngineFactory;
+import com.zd.common.core.utils.Assert;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+
 import static com.arcsoft.face.toolkit.ImageFactory.getRGBData;
 
 /**
@@ -33,49 +36,50 @@ public class FaceService {
 
     /**
      * 人脸检测
+     *
      * @param imageInfo 待检测的图片信息
      * @return
      */
-    public List<FaceInfo>  faceDetect(ImageInfo imageInfo)
-    {
-        List<FaceInfo> faceInfoList = new ArrayList<FaceInfo>();
+    public List<FaceInfo> faceDetect(ImageInfo imageInfo) throws IOException {
+        List<FaceInfo> faceInfoList = new ArrayList<>();
         int errorCode = faceEngineFactory.initFaceEngineImage().detectFaces(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList);
-        Assert.isTrue(errorCode==ErrorInfo.MOK.getValue(),"人脸检测失败!");
+        Assert.isTrue(errorCode == ErrorInfo.MOK.getValue(), "人脸检测失败!");
         return faceInfoList;
     }
 
 
-
     /**
      * 人脸特征提取
+     *
      * @return
      */
-    public FaceFeature faceFeature(ImageInfo imageInfo,List<FaceInfo> faceInfoList)
-    {
+    public FaceFeature faceFeature(ImageInfo imageInfo, List<FaceInfo> faceInfoList) {
         FaceFeature faceFeature = new FaceFeature();
         FaceEngine imageFaceEngine = null;
         int errorCode;
         try {
             imageFaceEngine = faceEngineFactory.initFaceEngineImage();
             errorCode = imageFaceEngine.extractFaceFeature(imageInfo.getImageData(), imageInfo.getWidth(), imageInfo.getHeight(), imageInfo.getImageFormat(), faceInfoList.get(0), faceFeature);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
         } finally {
-            if(imageFaceEngine!=null)
-            {
+            if (imageFaceEngine != null) {
                 imageFaceEngine.unInit();
             }
 
         }
 
-        Assert.isTrue(errorCode==ErrorInfo.MOK.getValue(),"人脸特征提取失败!");
+        Assert.isTrue(errorCode == ErrorInfo.MOK.getValue(), "人脸特征提取失败!");
 
         return faceFeature;
     }
+
     /**
      * 人脸对比
+     *
      * @return
      */
-    public Boolean compore(FaceFeature targetFaceFeature,FaceFeature sourceFaceFeature)
-    {
+    public Boolean compore(FaceFeature targetFaceFeature, FaceFeature sourceFaceFeature) {
 
         FaceSimilar faceSimilar = new FaceSimilar();
         FaceEngine faceEngine = null;
@@ -83,18 +87,18 @@ public class FaceService {
         try {
             faceEngine = faceEngineFactory.initFaceEngineImage();
             errorCode = faceEngine.compareFaceFeature(targetFaceFeature, sourceFaceFeature, faceSimilar);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
         } finally {
-            if(faceEngine!=null)
-            {
+            if (faceEngine != null) {
                 faceEngine.unInit();
             }
         }
-        Assert.isTrue(errorCode==ErrorInfo.MOK.getValue(),"人脸对比失败!");
-        return faceSimilar.getScore()>=faceProperties.getScore();
+        Assert.isTrue(errorCode == ErrorInfo.MOK.getValue(), "人脸对比失败!");
+        return faceSimilar.getScore() >= faceProperties.getScore();
     }
 
     public ImageInfo getImageInfo(File file) {
-        ImageInfo imageInfo = getRGBData(file);
-        return imageInfo;
+        return getRGBData(file);
     }
 }

zd-modules/zd-algorithm/src/main/resources/libs/arcsoft_lib/libarcsoft_face.so → zd-modules/zd-algorithm/src/main/resources/libs/3.0/LINUX64/libarcsoft_face.so


BIN
zd-modules/zd-algorithm/src/main/resources/libs/arcsoft_lib/libarcsoft_face_engine.so


zd-modules/zd-algorithm/src/main/resources/libs/arcsoft_lib/libarcsoft_face_engine_jni.so → zd-modules/zd-algorithm/src/main/resources/libs/3.0/LINUX64/libarcsoft_face_engine_jni.so


BIN
zd-modules/zd-algorithm/src/main/resources/libs/arcsoft_lib/libarcsoft_face.dll


BIN
zd-modules/zd-algorithm/src/main/resources/libs/3.0/WIN64/libarcsoft_face_engine.dll


BIN
zd-modules/zd-algorithm/src/main/resources/libs/3.0/WIN64/libarcsoft_face_engine_jni.dll


BIN
zd-modules/zd-algorithm/src/main/resources/libs/arcsoft_lib/libarcsoft_face_engine.dll


BIN
zd-modules/zd-algorithm/src/main/resources/libs/arcsoft_lib/libarcsoft_face_engine_jni.dll