mirror of
https://github.com/geekwenjie/SmartJavaAI.git
synced 2026-09-18 16:39:21 +00:00
集成算法seetaface6
This commit is contained in:
144
smartjavaai-face/src/main/java/com/seetaface/NativeLoader.java
Normal file
144
smartjavaai-face/src/main/java/com/seetaface/NativeLoader.java
Normal file
@@ -0,0 +1,144 @@
|
||||
package com.seetaface;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
/**
|
||||
* 依赖库加载器
|
||||
* @author dwj
|
||||
*/
|
||||
@Slf4j
|
||||
public class NativeLoader {
|
||||
|
||||
|
||||
private static Path tempNativeDir;
|
||||
private static final String[] WIN_LIBS = {"tennis","tennis_haswell","tennis_pentium","tennis_sandy_bridge","SeetaAuthorize","SeetaFaceAntiSpoofingX600","SeetaFaceDetector600","SeetaFaceLandmarker600","SeetaFaceRecognizer610","SeetaFace6JNI"};
|
||||
private static final String[] LINUX_CENTOS_LIBS = {"libmain.so"};
|
||||
private static final String[] LINUX_UBUNTU_LIBS = {"libdependency1.so", "libdependency2.so", "libmain.so"};
|
||||
|
||||
private static final String TEMP_DIR = "smartjavaai-native-libs";
|
||||
|
||||
public static SeetaFace6JNI seetaFace6SDK;
|
||||
|
||||
|
||||
|
||||
public static void loadNativeLibraries(String modelPath) {
|
||||
try {
|
||||
// 创建临时目录
|
||||
tempNativeDir = Files.createTempDirectory(TEMP_DIR);
|
||||
log.info("create temp native directory: " + tempNativeDir.toAbsolutePath().toString());
|
||||
|
||||
// 获取当前平台库列表
|
||||
String libDir = getLibDir();
|
||||
String[] libNames = getPlatformLibs(libDir);
|
||||
|
||||
// 批量提取库文件
|
||||
for (String libName : libNames) {
|
||||
extractLibrary(libName,libDir);
|
||||
}
|
||||
|
||||
String separator = System.getProperty("path.separator");
|
||||
String sysLib = System.getProperty("java.library.path");
|
||||
if (sysLib.endsWith(separator)) {
|
||||
System.setProperty("java.library.path", sysLib + tempNativeDir);
|
||||
} else {
|
||||
System.setProperty("java.library.path", sysLib + separator + tempNativeDir);
|
||||
}
|
||||
try {
|
||||
//使java.library.path生效
|
||||
Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
|
||||
sysPathsField.setAccessible(true);
|
||||
sysPathsField.set(null, null);
|
||||
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// 按顺序加载库(确保依赖关系)
|
||||
for (String libName : libNames) {
|
||||
System.loadLibrary(libName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Native library loading failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static String[] getPlatformLibs(String libDir) {
|
||||
if (libDir.contains("windows")) return WIN_LIBS;
|
||||
if (libDir.contains("centos")) return LINUX_CENTOS_LIBS;
|
||||
if (libDir.contains("ubuntu")) return LINUX_UBUNTU_LIBS;
|
||||
throw new UnsupportedOperationException("Unsupported OS");
|
||||
}
|
||||
|
||||
/**
|
||||
* 拷贝依赖库到临时目录
|
||||
* @param libName
|
||||
* @param libDir
|
||||
* @throws IOException
|
||||
*/
|
||||
private static void extractLibrary(String libName,String libDir) throws IOException {
|
||||
String resourcePath = "/native" + libDir + "/" + libName + ".dll";
|
||||
try (InputStream in = NativeLoader.class.getResourceAsStream(resourcePath)) {
|
||||
if (in == null) throw new FileNotFoundException(resourcePath);
|
||||
|
||||
Path targetPath = tempNativeDir.resolve(libName);
|
||||
Files.copy(in, targetPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
log.info("copy target path success : " + targetPath.toAbsolutePath().toString());
|
||||
|
||||
// 设置可执行权限
|
||||
if (!System.getProperty("os.name").toLowerCase().contains("win")) {
|
||||
targetPath.toFile().setExecutable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取依赖库目录
|
||||
* @return
|
||||
*/
|
||||
private static String getLibDir() {
|
||||
String osName = System.getProperty("os.name").toLowerCase();
|
||||
if (osName.contains("win")) {
|
||||
return "/windows";
|
||||
} else if (osName.contains("linux")) {
|
||||
String linuxOsName = getLinuxOsName();
|
||||
if(StringUtils.isBlank(linuxOsName)){
|
||||
throw new UnsupportedOperationException("Unsupported platform");
|
||||
};
|
||||
if(linuxOsName.contains("ubuntu")){
|
||||
return "/linux/ubuntu";
|
||||
}else if(linuxOsName.contains("centos")){
|
||||
return "/linux/centos";
|
||||
}
|
||||
}
|
||||
throw new UnsupportedOperationException("Unsupported platform");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 获取linux系统名称
|
||||
* @return
|
||||
*/
|
||||
private static String getLinuxOsName(){
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader("/etc/os-release"))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.startsWith("ID=")) {
|
||||
String distro = line.substring(3).replace("\"", "").trim();
|
||||
return distro;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.println("Failed to read /etc/os-release: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
127
smartjavaai-face/src/main/java/com/seetaface/SeetaFace6JNI.java
Normal file
127
smartjavaai-face/src/main/java/com/seetaface/SeetaFace6JNI.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package com.seetaface;
|
||||
|
||||
|
||||
import com.seetaface.model.RecognizeResult;
|
||||
import com.seetaface.model.SeetaImageData;
|
||||
import com.seetaface.model.SeetaPointF;
|
||||
import com.seetaface.model.SeetaRect;
|
||||
|
||||
/**
|
||||
* seetaface6 sdk
|
||||
* @author dwj
|
||||
*/
|
||||
public class SeetaFace6JNI {
|
||||
|
||||
/**
|
||||
* 初始化,指定人脸识别模型文件目录
|
||||
*
|
||||
* @param modelDir
|
||||
* @return
|
||||
*/
|
||||
|
||||
public native boolean initModel(String modelDir);
|
||||
|
||||
/**
|
||||
* 检测人脸
|
||||
*
|
||||
* @param img
|
||||
* @return
|
||||
*/
|
||||
public native SeetaRect[] detect(SeetaImageData img);
|
||||
|
||||
/**
|
||||
* 根据人脸检测关键点
|
||||
* 关键定定位输入的是原始图片和人脸检测结果,给出指定人脸上的关键点的依次坐标。
|
||||
* 这里检测到的5点坐标循序依次为,左眼中心、右眼中心、鼻尖、左嘴角和右嘴角。
|
||||
* 注意这里的左右是基于图片内容的左右,并不是图片中人的左右,即左眼中心就是图片中左边的眼睛的中心。
|
||||
*
|
||||
* @param img
|
||||
* @param faces
|
||||
* @return
|
||||
*/
|
||||
public native SeetaPointF[] mark(SeetaImageData img, SeetaRect faces);
|
||||
|
||||
/**
|
||||
* 1 v 1 人脸比对
|
||||
*
|
||||
* @param img1
|
||||
* @param img2
|
||||
* @return 相似度范围在0~1,返回负数表示出错
|
||||
*/
|
||||
public native float compare(SeetaImageData img1, SeetaImageData img2);
|
||||
|
||||
/**
|
||||
* 提取人脸区域特性
|
||||
* @param face crop方法返回的人脸图像
|
||||
* @return
|
||||
*/
|
||||
public native float[] extractCroppedFace(byte[] face);
|
||||
|
||||
/**
|
||||
* 提取一个图像中最大人脸的特征
|
||||
* @param img
|
||||
* @return
|
||||
*/
|
||||
public native float[] extractMaxFace(SeetaImageData img);
|
||||
|
||||
/**
|
||||
* 计算两个特性的相似度
|
||||
* @param features1
|
||||
* @param features2
|
||||
* @return
|
||||
*/
|
||||
public native float calculateSimilarity(float[] features1, float[] features2);
|
||||
|
||||
/**
|
||||
* 注册人脸
|
||||
*
|
||||
* @param img
|
||||
* @return The returned value is the index of face database. Reture -1 if failed
|
||||
*/
|
||||
public native long register(SeetaImageData img);
|
||||
|
||||
/**
|
||||
* 注册裁剪后的人脸,推荐使用该方法
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public native long registerCroppedFace(byte[] bytes);
|
||||
|
||||
/**
|
||||
* 从人脸库中搜索,返回相似度最高的索引
|
||||
*
|
||||
* @param img
|
||||
* @return index saves the index of face databese, which is same as the retured value by Register. similar saves the most similar.
|
||||
*/
|
||||
public native RecognizeResult query(SeetaImageData img);
|
||||
|
||||
/**
|
||||
* 用裁剪后的人脸进行搜索
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public native RecognizeResult queryByCroppedFace(byte[] bytes);
|
||||
|
||||
/**
|
||||
* 将人脸从数据库中删除
|
||||
* @param index -1: 删除所有
|
||||
* @return 返回删除记录数
|
||||
*/
|
||||
public native long delete(long[] index);
|
||||
|
||||
/**
|
||||
* 人脸提取
|
||||
*
|
||||
* @param img
|
||||
* @return The returned value is face data. Reture null if failed
|
||||
*/
|
||||
public native byte[][] crop(SeetaImageData img);
|
||||
|
||||
/**
|
||||
* 图片活体检测
|
||||
* @param img
|
||||
* @return
|
||||
*/
|
||||
public native int predictImage(SeetaImageData img);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.seetaface.model;
|
||||
|
||||
|
||||
/**
|
||||
* 人脸识别结果
|
||||
*/
|
||||
public class RecognizeResult {
|
||||
public int index;
|
||||
public float similar;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.seetaface.model;
|
||||
|
||||
/**
|
||||
* 人脸识别参数
|
||||
* @author dwj
|
||||
*/
|
||||
public class SeetaImageData {
|
||||
public SeetaImageData() {
|
||||
|
||||
}
|
||||
|
||||
public SeetaImageData(int width, int height, int channels) {
|
||||
this.data = new byte[width * height * channels];
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.channels = channels;
|
||||
}
|
||||
|
||||
public SeetaImageData(int width, int height) {
|
||||
this(width, height, 3);
|
||||
}
|
||||
|
||||
public byte[] data;
|
||||
public int width;
|
||||
public int height;
|
||||
public int channels;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.seetaface.model;
|
||||
|
||||
/**
|
||||
* SeetaPointF
|
||||
* @author dwj
|
||||
*/
|
||||
public class SeetaPointF {
|
||||
public double x;
|
||||
public double y;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.seetaface.model;
|
||||
|
||||
/**
|
||||
* SeetaPointF
|
||||
* @author dwj
|
||||
*/
|
||||
public class SeetaRect {
|
||||
public int x;
|
||||
public int y;
|
||||
public int width;
|
||||
public int height;
|
||||
public float score;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SeetaRect{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", width=" + width +
|
||||
", height=" + height +
|
||||
", score=" + score +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user