FaceRecog/Distribution/FaceSDKWrapper.java

195 lines
5.1 KiB
Java

package com.facesdk.wrapper;
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;
public class FaceSDKWrapper {
private static final String TAG = "FaceSDKWrapper";
static {
try {
System.loadLibrary("c++_shared");
System.loadLibrary("onnxruntime");
System.loadLibrary("opencv_java4");
System.loadLibrary("face_sdk_jni");
} catch (UnsatisfiedLinkError e) {
Log.e(TAG, "!!! 致命错误: 无法加载一个或多个 Native 库 !!!", e);
throw new RuntimeException("Failed to load native libraries", e);
}
}
private native long nativeInit(String modelDir);
private native float[] nativeExtractFeature(Bitmap bitmap);
private native float nativeCompare(float[] feat1, float[] feat2);
private native void nativeRelease();
private long nativeHandle = 0;
public boolean init(Context context) {
if (nativeHandle != 0) {
Log.w(TAG, "SDK already initialized.");
return true;
}
String modelPath = copyModelsFromAssets(context);
if (modelPath == null) {
Log.e(TAG, "Failed to copy models from assets.");
return false;
}
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;
}
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;
}
}
public float compare(float[] feat1, float[] feat2) {
if (nativeHandle == 0) {
Log.e(TAG, "SDK not initialized.");
return -2.0f;
}
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;
}
}
public void release() {
if (nativeHandle != 0) {
nativeRelease();
Log.i(TAG, "SDK Released. Handle: " + nativeHandle);
nativeHandle = 0;
}
}
private String copyModelsFromAssets(Context context) {
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"
};
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();
for (String filename : modelFiles) {
File outFile = new File(modelDir, filename);
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);
return null;
}
}
Log.i(TAG, "All models copied successfully to: " + modelDir.getAbsolutePath());
return modelDir.getAbsolutePath();
}
}