001package net.facelib.mtfsdk; 002 003import net.facelib.jni.BaseJniBridge; 004import net.facelib.jni.SdkInitException; 005import net.facelib.jni.SdkRuntime.RuntimeParam; 006import net.facelib.jni.SdkRuntimeException; 007import net.facelib.jni.SdkStatus; 008import net.gdface.utils.Assert; 009import net.gdface.utils.SimpleLog; 010 011import static net.facelib.mtfsdk.MtfsdkConstant.*; 012 013/** 014 * MTFSDK for android/arm JNI 接口<br> 015 * 此类为非线程安全的,不可多线程共享调用,需要在外部进一步封装实现线程安全 016 * @author guyadong 017 * 018 */ 019public class V2AndroidBridge extends BaseJniBridge{ 020 public static final String SDK_VERSION = "MTFSDK512V2"; 021 final long[] featureHandle = new long[1]; 022 /** 023 * 初始化状态 024 */ 025 private SdkStatus status=SdkStatus.SDK_UNINITIALIZED; 026 027 static { 028 try { 029 // 加载算法动态库 030 System.loadLibrary("FS_AndroidFeaV2SDK"); 031 } catch (Exception e) { 032 SimpleLog.log(e.getMessage()); 033 throw new ExceptionInInitializerError(e); 034 } 035 } 036 037 public V2AndroidBridge() { 038 } 039 040 /** 041 * 返回当前SDK初始化状态 042 * @return 043 */ 044 protected SdkStatus getStatus() { 045 return status; 046 } 047 /** 048 * 执行SDK(识别模块)初始化 049 * @param licenseKey 授权关键字 050 * @param licenseCode 授权码 051 * @return 初始化状态 052 */ 053 static SdkStatus ffInit(String licenseKey, String licenseCode,V2AndroidBridge instance) { 054 if(SdkStatus.SDK_INIT_OK == instance.status){ 055 return instance.status; 056 } 057 licenseCode = zeroEnd(licenseCode); 058 String szFilePath = "\0"; 059 String szCompanyNames = zeroEnd(licenseKey); 060 int ffFlag = FFInitV2(licenseCode.getBytes(), 061 szCompanyNames.getBytes(), 062 szFilePath.getBytes(), 063 szFilePath, 064 instance.featureHandle); 065 return SdkStatus.jniCode(ffFlag); 066 } 067 /** 068 * 执行SDK(检测模块,识别模块,活体检测模块)初始化,初始化失败则抛出异常 069 * @param licenseKey 授权关键字 070 * @param licenseCode 授权码 071 * @throws SdkInitException 072 */ 073 @Override 074 protected void sdkInit(String licenseKey, String licenseCode) throws SdkInitException { 075 if(SdkStatus.SDK_INIT_OK == status){ 076 return; 077 } 078 SdkStatus ffStatus = SdkStatus.SDK_UNINITIALIZED; 079 try{ 080 081 ffStatus = ffInit(licenseKey, licenseCode, this); 082 if(ffStatus !=SdkStatus.SDK_INIT_OK){ 083 status = ffStatus; 084 SimpleLog.log("feature module: {}", status.msg); 085 throw new SdkInitException(status); 086 } 087 088 // 检测模块和识别模块都初始化成功则置状态为成功 089 status = SdkStatus.SDK_INIT_OK; 090 }finally { 091 // 如果没有完全初始化成功,则destroy已经初始化模块 092 if(status != SdkStatus.SDK_INIT_OK){ 093 if(ffStatus !=SdkStatus.SDK_INIT_OK){ 094 FFDestroyV2(featureHandle[0]); 095 } 096 } 097 } 098 } 099 /** 100 * 人脸识别SDK资源释放 101 * @see #FDDestroy(long) 102 * @see #FFDestroyV2(long) 103 * @see #FLDestroy(long) 104 */ 105 @Override 106 protected void destroy() { 107 if(SdkStatus.SDK_INIT_OK == status){ 108 status = SdkStatus.SDK_UNINITIALIZED; 109 FFDestroyV2(featureHandle[0]); 110 } 111 } 112 public byte[] feaExtractByte(byte[] BGR, int width, int height, double[] rect){ 113 byte[] buffer = new byte[FEATURE_BYTES]; 114 int ret = FFFeaExtractByteV2(featureHandle[0], BGR, width, height, buffer, rect); 115 if(ret<0){ 116 throw new SdkRuntimeException(SdkStatus.jniCode(ret)); 117 } 118 return buffer; 119 } 120 @Override 121 public V2AndroidBridge setRuntimeParam(RuntimeParam name,Object value) throws SdkRuntimeException{ 122 Assert.notNull(name, "name"); 123 switch (name) { 124 case featureThreadNumber: 125 int featureThreadNumber = value != null ? (Integer) value : MtfAndroidConfigProvider.DEFAULT_FEATURE_THREAD_NUMBER; 126 if(featureThreadNumber > 0){ 127 int code = FFSetThreadsNumberV2(featureHandle[0], featureThreadNumber); 128 if(code != 0){ 129 status = SdkStatus.jniCode(code); 130 throw new SdkRuntimeException(status); 131 } 132 } 133 break; 134 default: 135 throw new IllegalArgumentException(SimpleLog.logString("INVALID parameter name: {}",name)); 136 } 137 return this; 138 } 139 ////////////////////////////////////////特征提取系列/////////////////////////////////////////// 140 /** 141 * 人脸识别初始化函数 142 * @param licenseCode 授权码 143 * @param licenseKey 授权关键字 144 * @param path 授权码文件本地路径 145 * @param faceDetectionModelPath 模型路径 146 * @param handle [out]句柄 147 * @return 成功(0)或错误代码(< 0),see also {@link SdkStatus} 148 */ 149 private static native int FFInitV2(byte[] licenseCode, byte[] licenseKey, byte[] path, String faceDetectionModelPath, long[] handle); 150 /** 151 * 人脸识别模块资源释放函数 152 * @param handle 句柄 153 */ 154 static native void FFDestroyV2(long handle); 155 156 /** 157 * 对输入图像中检测到的人脸提取特征 158 * @param handle 操作句柄 159 * @param BGR 待检测图像BGR格式 160 * @param width 图像宽度 161 * @param height 图像高度 162 * @param fea [out] 人脸特征 空间在外部申请,长度4096 163 * @param rect 人脸位置及关键点信息 由人脸检测SDK 产生,参见 {@link #FDDetect(long, byte[], int, int, int, double[])} 164 * @return 成功(0)或错误代码(< 0),see also {@link SdkStatus} 165 */ 166 private static native int FFFeaExtractByteV2(long handle, byte[] BGR, int width, int height, byte[] fea, double[] rect); 167 168 /** 169 * 人脸相似度比对函数<br> 170 * 对人脸特征feaA和feaB进行相似度比对,返回相似度结果 171 * @param feaA 1024 bytes 172 * @param feaB 1024 bytes 173 * @return 相似度(0.0~1.0) 174 */ 175 public static native double FFSimilarityByteV2(byte[] feaA, byte[] feaB); 176 177 /** 178 * @return 人脸识别模块版本 179 */ 180 public static native String FFgetVersionV2(); 181 private static native int FFSetThreadsNumberV2(long handle, int threadsNumbers); 182}