net.facelib.mtfsdk.BaseFaceApiMtfAndroid Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mtfsdk-android-common Show documentation
Show all versions of mtfsdk-android-common Show documentation
mtfsdk common(detection included) for android
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