net.facelib.live.FaceLiveAndroidFacelibImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of facelive Show documentation
Show all versions of facelive Show documentation
detect live face for video stream
package net.facelib.live;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import net.facelib.akcore.LicenseManager;
import net.facelib.akcore.ProductInitStatus;
import net.facelib.jni.BaseJniBridge;
import net.facelib.jni.BridgePool;
import net.gdface.image.BaseLazyImage;
import net.gdface.image.ImageErrorException;
import net.gdface.image.MatType;
import net.gdface.sdk.FRect;
import static com.google.common.base.Preconditions.checkArgument;
import static net.facelib.live.FaceLiveBridge.FACE_LIVE_PRODUCT_ID;
/**
* 活体检测 android/arm平台(线程安全)
* 基于commons-pools将非线程安全的{@link FaceLiveBridge}实例用资源池{@link GenericObjectPool}管理,
* 每次调用前从资源池申请一个{@link FaceLiveBridge}实例来使用,用完后归还资源池,
* 以实现对{@link FaceLiveBridge}实例线程安全的调用
* @author guyadong
*
*/
public class FaceLiveAndroidFacelibImpl extends FaceLiveAndroid{
private static volatile FaceLiveAndroidFacelibImpl INSTANCE;
private static class Singleton{
/**
* 资源池默认参数配置,
* SPI方式加载实例时,似乎不会执行类的静态成员初始化,所以将 poolConfig 移到私有静态类 Singleton 中以确保能在SPI方式下被正确初始化
*/
private static GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
}
private final BridgePool poolWrap;
public FaceLiveAndroidFacelibImpl() {
poolWrap = new BridgePool<>(FaceLiveBridge.class,Singleton.poolConfig);
}
@Override
public void bindNativeInstanceForCurentThread(){
poolWrap.bindInstanceForCurentThread();
}
@Override
public void unbindNativeInstanceForCurentThread(){
poolWrap.unbindInstanceForCurentThread();
}
@Override
public LicenseManager getLicenseManager(){
return FaceLiveBridge.LICENSE_MANAGER;
}
/**
* 执行活体检测
* @param matType 矩阵类型
* @param matData 矩阵图像
* @param width 图像宽度
* @param height 图像高度
* @param rect 人脸检测方法返回的人脸检测信息原始数据
* @param score [out]活体检测得分
* @param matData 输入的BGR格式图像
* @return 0--非活体,1--活体,2--缓存标志,3--未知,<0 错误代码
*/
@Override
public int nativeLiveProcess(MatType matType, byte[] matData , int width, int height,double[] rect, AtomicReferencescore){
FaceLiveBridge instance = poolWrap.applyInstance();
try{
return instance.liveProcess(matType , matData, width, height,rect, score);
}finally {
poolWrap.returnInstance(instance);
}
}
/**
* 执行活体检测
* @param platformImage 当前平台的图像对象,对于android平台,类型为Bitmap,对于通用JDK,类型为BufferedImage
* @param rect 人脸检测方法返回的人脸检测信息原始数据
* @return 0--非活体,1--活体,2--缓存标志,3--未知,<0 错误代码
* @deprecated 兼容要求保持,replaced by {@link #liveProcess(Object, FRect, AtomicReference)}
*/
public int liveProcess(Object platformImage,double[] rect){
return liveProcess(platformImage,rect,null);
}
/**
* 执行活体检测
* @param platformImage 当前平台的图像对象,对于android平台,类型为Bitmap,对于通用JDK,类型为BufferedImage
* @param rect 人脸检测方法返回的人脸检测信息原始数据
* @param score [out]活体检测得分
* @return 0--非活体,1--活体,2--缓存标志,3--未知,<0 错误代码
* @deprecated 兼容要求保持,replaced by {@link #liveProcess(Object, FRect, AtomicReference)}
*/
public int liveProcess(Object platformImage,double[] rect,AtomicReferencescore){
try {
BaseLazyImage lazyImage = BaseLazyImage.getLazyImageFactory().create(platformImage);
return nativeLiveProcess(getNativeMatType(),lazyImage.getMatrixBGR(),lazyImage.getWidth(),lazyImage.getHeight(),rect, score);
} catch (ImageErrorException e) {
throw new RuntimeException(e);
}
}
@Override
public int liveProcess(MatType matType,byte[] matData, int width, int height, FRect rect,AtomicReference score){
checkArgument(rect != null, "rect is null");
double[] dr = new double[21];
dr[0] = rect.getLeft();
dr[1] = rect.getTop();
dr[2] = rect.getWidth();
dr[3] = rect.getHeight();
dr[20] = 2D;
return nativeLiveProcess(matType,matData,width,height,dr, score);
}
@Override
public LiveStatus matLiveProcess(MatType matType, byte[] matData, int width, int height, FRect rect,
AtomicReference score) {
int code = liveProcess(matType, matData, width, height, rect, score);
return toLiveStatus(code);
}
@Override
public String getProductID() {
return FACE_LIVE_PRODUCT_ID;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("FaceLiveAndroidFacelibImpl [ProductID=");
builder.append(getProductID());
builder.append("]");
return builder.toString();
}
/**
* 测试是否可以正常初始化活体检测算法实例
* @param initMills [out]如果不为{@code null}返回返回初始化耗时(毫秒)
* @return 产品初始化状态
*/
public ProductInitStatus testInit(AtomicLong initMills) {
return BaseJniBridge.testInit(initMills, FaceLiveBridge.class);
}
@Override
protected MatType getNativeMatType() {
return MatType.BGR;
}
private static LiveStatus toLiveStatus(int code){
switch (code) {
case 0:
return LiveStatus.NOT_LIVE;
case 1:
return LiveStatus.LIVE;
case 2:
return LiveStatus.UNKNOW;
default:
NativeStatus.setNativeStatus(new NativeStatus(code, null));
return LiveStatus.LIVE_ERROR;
}
}
/**
* @return 返回活体检测算法实例资源池对象
*/
public GenericObjectPool getLivePool() {
return poolWrap.getPool();
}
/**
* 返回活体检测算法资源池对象参数配置
* @return poolConfig
*/
public static GenericObjectPoolConfig getPoolConfig() {
return Singleton.poolConfig;
}
/**
* 设置活体检测算法资源池对象参数配置
* @param poolConfig 要设置的 poolConfig
*/
public static void setPoolConfig(GenericObjectPoolConfig poolConfig) {
if(null != poolConfig){
Singleton.poolConfig = poolConfig;
}
}
public static FaceLiveAndroidFacelibImpl getInstance(){
// double check
if(null == INSTANCE){
synchronized (FaceLiveAndroidFacelibImpl.class) {
if(null == INSTANCE){
INSTANCE = new FaceLiveAndroidFacelibImpl();
}
}
}
return INSTANCE;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy