All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.facelib.mtfsdk.BaseFaceApiMtfAndroid Maven / Gradle / Ivy

The newest version!
package net.facelib.mtfsdk;

import java.util.List;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import com.gitee.l0km.com4j.base.SPIUtils;
import com.gitee.l0km.com4j.base.ShareLock;
import com.gitee.l0km.ximage.BaseLazyImage;
import com.gitee.l0km.ximage.ImageErrorException;
import com.gitee.l0km.ximage.MatType;
import com.gitee.l0km.ximage.android.LazyImage;

import android.graphics.Bitmap;
import net.facelib.akcore.ProductInitStatus;
import net.facelib.jni.BaseJniBridge;
import net.facelib.jni.BridgePool;
import net.facelib.jni.FacelibRuntimeParam;
import net.facelib.jni.SdkRuntime;
import net.gdface.sdk.BaseFaceApiLocal;
import net.gdface.sdk.CodeInfo;
import net.gdface.sdk.ContextLoader;
import net.gdface.sdk.NotFaceDetectedException;
import net.gdface.sdk.ContextLoader.GlobalContextField;
import net.gdface.sdk.fse.FeatureSe;

/**
 * MTFSDK android/arm平台 {@link net.gdface.sdk.FaceApi}接口实现抽象类(线程安全)
* @author guyadong * */ public abstract class BaseFaceApiMtfAndroid extends BaseFaceApiLocal implements MtfsdkConstant{ /** * 资源池默认参数配置 */ private static GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); /** * 应用层提供的{@link MtfAndroidConfigProvider}接口实例,未提供则初始化为{@link DefaultMtfAndroidConfig}实例 */ public static final MtfAndroidConfigProvider CONFIG = SPIUtils.loadProvider(MtfAndroidConfigProvider.class, new DefaultMtfAndroidConfig()); /** * 用于人脸检测的数据缓冲区 */ private static final ThreadLocal faceBuffer = new ThreadLocal(){ @Override protected double[] initialValue() { return new double[FDDATA_LEN*MAX_FACE_COUNT]; } }; /** * 人脸检测算法实例资源池 */ private final BridgePool poolWrap = new BridgePool<>(DetectAndroidArmBridge.class,poolConfig); public final SdkRuntime sdkRuntime = new SdkRuntime(FacelibRuntimeParam.class); protected BaseFaceApiMtfAndroid() { capacity.put(C_FDDATA_SIZE, "" + FDDATA_BYTES); capacity.put(C_FDMAX_FACE_COUNT, "" + MAX_FACE_COUNT); capacity.put(C_FEATURE_SIZE, "" + FEATURE_BYTES); capacity.put(C_CODEINFO_RELOCATE, Boolean.TRUE.toString()); } /** * 根据FaceApi应用上下文中获取{@link GlobalContextField.MULIT_FACE_DETECT_TREND}定义的值返回外部定义的检测模式(整数)
* 如果值为布尔值则为{@code true}时转为0,为{@code false}转为1, * 如果值为数字{@link Number}则直接返回对应的整数值, * 如果值类型非数字或布尔类型则抛出 {@link IllegalArgumentException} 异常, * 输入为{@code null}返回 0 * */ private static int getDetectMode() { Object value = ContextLoader.getContext(GlobalContextField.MULIT_FACE_DETECT_TREND); if (value instanceof Boolean) { return (Boolean) value ? 0 : 1; } else if (value instanceof Number) { return ((Number) value).intValue(); } else if (null != value) { throw new IllegalArgumentException( "INVOLID type " + value.getClass().getName() + ",boolean or number required"); } return 0; } /** * 清除本地参数设置 */ @Override public void reset (){ sdkRuntime.removeLocalRunTimeParam(); } @Override public void bindNativeDetectInstanceForCurentThread(){ poolWrap.bindInstanceForCurentThread(); } @Override public void unbindNativeDetectInstanceForCurentThread(){ poolWrap.unbindInstanceForCurentThread(); } /** * 人脸检测,最多返回三张人脸 */ @Override protected void nativeDetectFace(MatType matType, byte[] imgMatrix, int width, int height, List faceInfo) { nativeDetectFace(matType, imgMatrix, width, height, faceInfo, sdkRuntime.getRuntimeParam(FacelibRuntimeParam.detectMode.name(), getDetectMode())); } /** * 人脸检测,最多返回三张人脸 * @see DetectAndroidArmBridge#detect(MatType, byte[], int, int, int, double[]) */ protected void nativeDetectFace(MatType matType, byte[] imgMatrix, int width, int height,List faceInfo, int detectMod) { double[] buffer = faceBuffer.get(); DetectAndroidArmBridge instance = poolWrap.applyInstance(); try{ sdkRuntime.setInstanceParam(instance,FacelibRuntimeParam.detectThreadNumber.name()); sdkRuntime.setInstanceParam(instance,FacelibRuntimeParam.minFaceSize.name()); int res = instance.detect(matType, imgMatrix, width, height, detectMod, buffer); for(int i=0; i < res; ++i){ faceInfo.add(new NativeFaceInfo(buffer, i*FDDATA_LEN)); } }finally { poolWrap.returnInstance(instance); } } /** * 执行单人脸检测,返回最大人脸位置信息 * @param matType 图像矩阵类型 * @param imgMatrix 图像矩阵 * @param width 图像宽度 * @param height 图像高度 * @param detectMod 0:用于检测图片,1:用于视频的循环检测 * @return 人脸检测信息描述对象 */ protected NativeFaceInfo nativeDetectMaxFace(MatType matType, byte[] imgMatrix, int width, int height, int detectMod) { double[] buffer = faceBuffer.get(); DetectAndroidArmBridge instance = poolWrap.applyInstance(); try{ sdkRuntime.setInstanceParam(instance,FacelibRuntimeParam.detectThreadNumber.name()); sdkRuntime.setInstanceParam(instance,FacelibRuntimeParam.minFaceSize.name()); int res = instance.detectMaxFace(matType, imgMatrix, width, height, detectMod, buffer); return res ==0 ? null : new NativeFaceInfo(buffer, 0); }finally { poolWrap.returnInstance(instance); } } @Override public CodeInfo matDetectMaxFace(MatType matType,byte[] matData,int width, int height) throws NotFaceDetectedException { NativeFaceInfo nativeFaceInfo = nativeDetectMaxFace(matType, matData, width, height, sdkRuntime.getRuntimeParam(FacelibRuntimeParam.detectMode.name(), getDetectMode())); if(null == nativeFaceInfo ){ throw new NotFaceDetectedException(); } return nativeFaceInfo; } /** * @see #nativeDetectMaxFace(MatType, byte[], int, int, int) */ public NativeFaceInfo detectMaxFace(Bitmap bitmap, int detectMod) { try { byte[] matrix = BaseLazyImage.getLazyImageFactory().create(bitmap).getMatrixData(getNativeMatrixType()); return nativeDetectMaxFace(getNativeMatrixType(),matrix,bitmap.getWidth(), bitmap.getHeight(), detectMod); } catch (ImageErrorException e) { throw new RuntimeException(e); } } /** * 检测人脸 * @param bitmap * @return 人脸特征码信息描述对象列表 * @see #detectFace(com.gitee.l0km.ximage.BaseLazyImage) */ public List detectFace(Bitmap bitmap){ try { return detectFace(BaseLazyImage.getLazyImageFactory().create(bitmap)); } catch (ImageErrorException e) { throw new RuntimeException(e); } } /** * 位置关联 * 在人脸检测函数后用到,无论有无检测到人脸,均需要调用,从属于检测系列 * @param faceNums 人脸个数 * @param rectRate * @param faceRect 人脸信息(人脸检测数据rect) 21个元素 * @param faceRectInfo [out]返回的标记,最后一个元素为是否成功比对的标志,其他为人脸信息 * @return 位置关联总个数 */ public int facePosInterrelate(int faceNums, double rectRate, double[] faceRect, double[] faceRectInfo){ DetectAndroidArmBridge instance = poolWrap.applyInstance(); try{ return instance.facePosInterrelate(faceNums, rectRate, faceRect, faceRectInfo); }finally { poolWrap.returnInstance(instance); } } public int setFacePosStatus(int facePos, int flag){ DetectAndroidArmBridge instance = poolWrap.applyInstance(); try{ return instance.setFacePosStatus(facePos, flag); }finally { poolWrap.returnInstance(instance); } } /** * 提取特征 * @param bitmap 图像数据对象 * @param faceNum 要求提取特征的人脸数量 * @param facePos 包含人脸位置信息的{@link CodeInfo}列表 * @return 包含人脸特征信息的{@link CodeInfo}列表 * @throws NotFaceDetectedException * @see #getCodeInfo(com.gitee.l0km.ximage.BaseLazyImage, int, List) */ public List getCodeInfo(Bitmap bitmap, int faceNum, List facePos) throws NotFaceDetectedException{ return getCodeInfo(LazyImage.create(bitmap), faceNum, facePos); } /** * 提取单个人脸特征 * @param bitmap 图像数据对象 * @param facePos 包含人脸位置信息的{@link CodeInfo} * @return 包含人脸特征信息的{@link CodeInfo}对象 */ public CodeInfo getCodeInfo(Bitmap bitmap, CodeInfo facePos){ return getCodeInfo(LazyImage.create(bitmap), facePos); } /** * 检测并提取人脸特征 * @param bitmap 图像数据对象 * @param faceNum 要求提取特征的人脸数量 * @return 包含人脸特征信息的{@link CodeInfo}对象数组 * @throws NotFaceDetectedException * @see #detectAndGetCodeInfo(BaseLazyImage, int) */ public CodeInfo[] detectAndGetCodeInfo(Bitmap bitmap, int faceNum) throws NotFaceDetectedException { try { return detectAndGetCodeInfo(LazyImage.create(bitmap).open(), faceNum); } catch (ImageErrorException e) { throw new RuntimeException(e); } } @Override public FeatureSe getFeatureSe() { return FseMtfAndroidBridge.getFeatureSe(); } /** * 测试是否可以正常初始化人脸检测算法实例 * @param initMills [out]如果不为{@code null}返回返回初始化耗时(毫秒) * @return 产品初始化状态 */ public ProductInitStatus testDetectInit(AtomicLong initMills) { return BaseJniBridge.testInit(initMills,DetectAndroidArmBridge.class); } /** * @return 返回人脸检测算法实例资源池对象 */ public GenericObjectPool getDetectPool() { return poolWrap.getPool(); } static { try { // MTFSDK JNI接口静态区初始化 Class.forName(net.facelib.mtfsdk.DetectAndroidArmBridge.class.getName()); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(e); } // 要在动态库加载后调用,因为方法中可能会调用动态库中的函数 // licenseManager().installLicenseIfSPIAvailable(); // 根据配置参数设置并发线程数 int concurrency = CONFIG.getConcurrency(); if(concurrency > 0){ concurrentLock = new ShareLock(concurrency); } } /** * 返回人脸检测算法资源池对象参数配置 * @return poolConfig */ public static GenericObjectPoolConfig getPoolConfig() { return poolConfig; } /** * 设置人脸检测算法资源池对象参数配置 * @param poolConfig 要设置的 poolConfig */ public static void setPoolConfig(GenericObjectPoolConfig poolConfig) { if(null != poolConfig){ BaseFaceApiMtfAndroid.poolConfig = poolConfig; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy