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}