FaceRecog/Distribution/FaceSDKWrapper.java

195 lines
5.1 KiB
Java
Raw Normal View History

2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
package com.facesdk.wrapper;
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.util.Log;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
public class FaceSDKWrapper {
private static final String TAG = "FaceSDKWrapper";
static {
try {
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
System.loadLibrary("c++_shared");
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
System.loadLibrary("onnxruntime");
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
System.loadLibrary("opencv_java4");
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
System.loadLibrary("face_sdk_jni");
} catch (UnsatisfiedLinkError e) {
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
Log.e(TAG, "!!! 致命错误: 无法加载一个或多个 Native 库 !!!", e);
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
throw new RuntimeException("Failed to load native libraries", e);
}
}
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
private native long nativeInit(String modelDir);
private native float[] nativeExtractFeature(Bitmap bitmap);
private native float nativeCompare(float[] feat1, float[] feat2);
private native void nativeRelease();
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
private long nativeHandle = 0;
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
public boolean init(Context context) {
if (nativeHandle != 0) {
Log.w(TAG, "SDK already initialized.");
return true;
}
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
String modelPath = copyModelsFromAssets(context);
if (modelPath == null) {
Log.e(TAG, "Failed to copy models from assets.");
return false;
}
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
try {
this.nativeHandle = nativeInit(modelPath);
if (this.nativeHandle == 0) {
Log.e(TAG, "JNI nativeInit() returned 0 (Init failed).");
return false;
}
} catch (Exception e) {
Log.e(TAG, "Exception during nativeInit()", e);
return false;
}
Log.i(TAG, "SDK Initialized successfully. Handle: " + this.nativeHandle);
return true;
}
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
public float[] extractFeature(Bitmap bitmap) {
if (nativeHandle == 0) {
Log.e(TAG, "SDK not initialized. Call init() first.");
return null;
}
if (bitmap == null) {
Log.e(TAG, "Input bitmap is null.");
return null;
}
try {
return nativeExtractFeature(bitmap);
} catch (Exception e) {
Log.e(TAG, "Exception during nativeExtractFeature()", e);
return null;
}
}
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
public float compare(float[] feat1, float[] feat2) {
if (nativeHandle == 0) {
Log.e(TAG, "SDK not initialized.");
2025-11-17 15:54:25 +08:00
return -2.0f;
2025-10-31 13:59:24 +08:00
}
if (feat1 == null || feat2 == null || feat1.length != 512 || feat2.length != 512) {
Log.e(TAG, "Invalid feature vectors for comparison.");
return -2.0f;
}
try {
return nativeCompare(feat1, feat2);
} catch (Exception e) {
Log.e(TAG, "Exception during nativeCompare()", e);
return -2.0f;
}
}
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
public void release() {
if (nativeHandle != 0) {
nativeRelease();
Log.i(TAG, "SDK Released. Handle: " + nativeHandle);
nativeHandle = 0;
}
}
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
private String copyModelsFromAssets(Context context) {
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
final String[] modelFiles = {
"faceboxesv2-640x640.onnx",
"face_landmarker_pts5_net1.onnx",
"face_landmarker_pts5_net2.onnx",
"face_recognizer.onnx",
"model_gray_mobilenetv2_rotcls.onnx",
"fsanet-var.onnx",
"fsanet-conv.onnx"
};
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
File modelDir = new File(context.getFilesDir(), "models");
if (!modelDir.exists()) {
if (!modelDir.mkdirs()) {
Log.e(TAG, "Failed to create directory: " + modelDir.getAbsolutePath());
return null;
}
}
AssetManager assetManager = context.getAssets();
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
for (String filename : modelFiles) {
File outFile = new File(modelDir, filename);
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
if (outFile.exists()) {
Log.i(TAG, "Model exists, skipping: " + filename);
continue;
}
Log.i(TAG, "Copying model: " + filename);
try (InputStream is = assetManager.open(filename);
OutputStream os = new FileOutputStream(outFile)) {
byte[] buffer = new byte[1024 * 4];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
Log.e(TAG, "Failed to copy model: " + filename, e);
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
return null;
}
}
Log.i(TAG, "All models copied successfully to: " + modelDir.getAbsolutePath());
2025-11-17 15:54:25 +08:00
2025-10-31 13:59:24 +08:00
return modelDir.getAbsolutePath();
}
}