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
package net.facelib.mtfsdk;
import java.util.List;
import android.graphics.Bitmap;
import net.facelib.jni.BaseJniBridge;
import net.facelib.jni.BridgePool;
import net.facelib.jni.SdkRuntime;
import net.facelib.jni.SdkRuntime.RuntimeParam;
import net.gdface.image.BaseLazyImage;
import net.gdface.image.ImageErrorException;
import net.gdface.image.LazyImage;
import net.gdface.license.LicenseManager;
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;
import net.gdface.utils.BaseVolatile;
import net.gdface.utils.ILazyInitVariable;
import net.gdface.utils.SPIUtils;
import net.gdface.utils.ShareLock;
import static net.facelib.mtfsdk.DetectAndroidArmBridge.DEFAULT_LICENSE_MANAGER;
/**
* MTFSDK android/arm平台 {@link net.gdface.sdk.FaceApi}接口实现抽象类(线程安全)
* @author guyadong
*
*/
public abstract class BaseFaceApiMtfAndroid extends BaseFaceApiLocal implements MtfsdkConstant{
/**
* 应用层提供的{@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];
}
};
/**
* 返回人脸检测倾向
* 先尝试从全局上下文({@link ContextLoader})获取,
* 如果找不到则返回true为默认值
*/
private static final ILazyInitVariable mulitFaceDetectDrend = new BaseVolatile(){
@Override
protected Integer doGet() {
Boolean mfd = ContextLoader.getGlobalcontext(GlobalContextField.MULIT_FACE_DETECT_TREND);
if(null == mfd){
return 0;
}
return mfd ? 0 : 1;
}};
private final BridgePool poolWrap = new BridgePool<>(DetectAndroidArmBridge.class);
public final SdkRuntime sdkRuntime = new SdkRuntime();
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());
}
/**
* @return 返回SDK的授权信息管理实例
*/
public static LicenseManager licenseManager(){
return BaseJniBridge.getLicenseManager(DEFAULT_LICENSE_MANAGER);
}
/**
* 人脸检测,最多返回三张人脸
*/
public void nativeDetectFace(byte[] imgMatrix, int width, int height, List faceInfo) {
nativeDetectFace(imgMatrix, width, height, faceInfo, mulitFaceDetectDrend.get());
}
/**
* 人脸检测,最多返回三张人脸
* @see DetectAndroidArmBridge#detect(byte[], int, int, int, double[])
*/
public void nativeDetectFace(byte[] imgMatrix, int width, int height, List faceInfo,int detectMod) {
double[] buffer = faceBuffer.get();
DetectAndroidArmBridge instance = poolWrap.applyInstance();
try{
sdkRuntime.setInstanceParam(instance,RuntimeParam.detectThreadNumber);
sdkRuntime.setInstanceParam(instance,RuntimeParam.minFaceSize);
int res = instance.detect(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 imgMatrix
* @param width
* @param height
* @param detectMod 0:用于检测图片,1:用于视频的循环检测
* @return
*/
public NativeFaceInfo nativeDetectMaxFace(byte[] imgMatrix, int width, int height, int detectMod) {
double[] buffer = faceBuffer.get();
DetectAndroidArmBridge instance = poolWrap.applyInstance();
try{
sdkRuntime.setInstanceParam(instance,RuntimeParam.detectThreadNumber);
sdkRuntime.setInstanceParam(instance,RuntimeParam.minFaceSize);
int res = instance.detectMaxFace(imgMatrix, width, height, detectMod, buffer);
return res ==0 ? null : new NativeFaceInfo(buffer, 0);
}finally {
poolWrap.returnInstance(instance);
}
}
/**
* @see #nativeDetectMaxFace(byte[], int, int, int)
*/
public NativeFaceInfo detectMaxFace(Bitmap bitmap, int detectMod) {
try {
byte[] matrix = BaseLazyImage.getLazyImageFactory().create(bitmap).getMatrixData(getNativeMatrixType());
return nativeDetectMaxFace(matrix,bitmap.getWidth(),bitmap.getHeight(), detectMod);
} catch (ImageErrorException e) {
throw new RuntimeException(e);
}
}
/**
* 检测人脸
* @param bitmap
* @return
* @see #detectFace(net.gdface.image.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
* @return
* @throws NotFaceDetectedException
* @see #getCodeInfo(net.gdface.image.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
* @return
*/
public CodeInfo getCodeInfo(Bitmap bitmap, CodeInfo facePos){
return getCodeInfo(LazyImage.create(bitmap), facePos);
}
/**
* 检测并提取人脸特征
* @param bitmap
* @param faceNum
* @return
* @throws NotFaceDetectedException
* @see {@link BaseFaceApiLocal#detectAndGetCodeInfo(net.gdface.image.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();
}
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);
}
}
}