net.facelib.mtfsdk.NativeFaceInfo 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 static net.facelib.mtfsdk.NativeFaceInfo.FieldIndex.*;
import static net.gdface.utils.BufferUtils.*;
import net.gdface.sdk.CodeInfo;
import net.gdface.sdk.EyeInfo;
import net.gdface.sdk.FAngle;
import net.gdface.sdk.FInt2;
import net.gdface.sdk.FRect;
import net.gdface.utils.Assert;
/**
* 人脸检测信息描述对象
* 实现原始人脸检测数据(double[])的解析,以及与{@link CodeInfo}实例的相互转换
* @author guyadong
*
*/
public class NativeFaceInfo extends CodeInfo implements MtfsdkConstant {
/**
* 人脸检测数据(double数组)的字段名索引
* @author guyadong
*
*/
enum FieldIndex{
/* 人脸位置矩形左上角 x */FRECT_LEFT,
/* 人脸位置矩形左上角 y */FRECT_TOP,
/* 人脸位置矩形宽度 */FRECT_WIDTH,
/* 人脸位置矩形高度 */FRECT_HEIGHT,
/* 人脸关键点 0 x坐标:左眼 */FD_LEFT_EYE_X,
/* 人脸关键点 0 y坐标:左眼 */FD_LEFT_EYE_Y,
/* 人脸关键点 1 x坐标:右眼 */FD_RIGHT_EYE_X,
/* 人脸关键点 1 y坐标:右眼 */FD_RIGHT_EYE_Y,
/* 人脸关键点 2 x坐标:鼻子 */FD_NOSE_X,
/* 人脸关键点 2 y坐标:鼻子 */FD_NOSE_Y,
/* 人脸关键点 3 x坐标:左嘴角*/FD_MOUTH_LEFT_X,
/* 人脸关键点 3 y坐标:左嘴角 */FD_MOUTH_LEFT_Y,
/* 人脸关键点 4 x坐标:右嘴角*/FD_MOUTH_RIGHT_X,
/* 人脸关键点 4 y坐标:右嘴角 */FD_MOUTH_RIGHT_Y,
/* 置信度 */FD_CONFIDENCE,
/* 人脸框预测x步进值,只有在使用位置关联函数才有赋值 */FD_FACE_OFFSET_Y,
/* 人脸框预测y步进值,只有在使用位置关联函数才有赋值 */FD_FACE_OFFSET_X,
/* 人脸姿态角度:旋转角roll */FD_ANGLE_ROLL,
/* 人脸姿态角度:偏转角yaw */FD_ANGLE_YAW,
/* 人脸姿态角度:倾斜角pitch */FD_ANGLE_PITCH,
/* 识别标记(是否已经识别) */FD_DETECTED_FLAG,
}
private static final long serialVersionUID = 1L;
/**
* 人脸检测框置信度(与{@link FAngle#getConfidence()}相同)
*/
double confidence;
/**
* 从JNI动态库返回的原始人脸检测数据 double[61]
*/
double nativeData[];
public NativeFaceInfo(double[] nativeData) {
this(nativeData,0);
}
/**
* 从原始人脸信息数组构造实例
* @param nativeData 原始数据
* @param start 数据起始索引
*/
public NativeFaceInfo(double[] nativeData,int start) {
super();
init(nativeData, start);
}
public NativeFaceInfo(CodeInfo codeInfo) {
super();
Assert.notNull(codeInfo, "codeinfo");
byte[] facialData = codeInfo.getFacialData();
Assert.notNull(facialData, "facialData");
init(asDoubleArray(facialData), 0);
setOffset(codeInfo.getOffset());
}
/**
* 从原始人脸检测数据(61个double)解析为当前对象对应字段
* @param nativeData
* @param start
*/
private void init(double[] nativeData, int start){
Assert.isTrue(start>=0,"start>=0", "invalid start");
Assert.isTrue(nativeData!=null && nativeData.length-start>=FDDATA_LEN,
"nativeData!=null && nativeData.length-start>=CaffeMobile.FDDATA_LEN","invalid nativeData");
this.nativeData = new double[FDDATA_LEN];
System.arraycopy(nativeData, start, this.nativeData, 0, this.nativeData.length);
////////////////////
FRect pos = getPos();
if(pos == null){
pos = new FRect();
}
pos.setLeft((int) this.nativeData[FRECT_LEFT.ordinal()]);
pos.setTop((int) this.nativeData[FRECT_TOP.ordinal()]);
pos.setWidth((int) this.nativeData[FRECT_WIDTH.ordinal()]);
pos.setHeight((int) this.nativeData[FRECT_HEIGHT.ordinal()]);
setPos(pos);
/////////////////////////
FAngle angle = getAngle();
if(angle == null){
angle = new FAngle();
}
angle.setRoll((int) this.nativeData[FD_ANGLE_ROLL.ordinal()]);
angle.setYaw((int) this.nativeData[FD_ANGLE_YAW.ordinal()]);
angle.setPitch((int) this.nativeData[FD_ANGLE_PITCH.ordinal()]);
angle.setConfidence((int)(this.nativeData[FD_CONFIDENCE.ordinal()]*100));
setAngle(angle);
//////////////////////////
EyeInfo ei = getEi();
if(ei == null){
ei = new EyeInfo();
}
ei.setLeftx((int)this.nativeData[FD_LEFT_EYE_X.ordinal()]);
ei.setLefty((int)this.nativeData[FD_LEFT_EYE_Y.ordinal()]);
ei.setRightx((int)this.nativeData[FD_RIGHT_EYE_X.ordinal()]);
ei.setRighty((int)this.nativeData[FD_RIGHT_EYE_Y.ordinal()]);
setEi(ei);
//////////////////////////
FInt2 mouth = getMouth();
if(mouth == null){
mouth = new FInt2();
}
{
// 计算左右眼中间点位置
double x = (this.nativeData[FD_MOUTH_LEFT_X.ordinal()]
+ this.nativeData[FD_MOUTH_RIGHT_X.ordinal()])/2;
double y = (this.nativeData[FD_MOUTH_LEFT_Y.ordinal()]
+ this.nativeData[FD_MOUTH_RIGHT_Y.ordinal()])/2;
mouth.setX((int)x);
mouth.setY((int)y);
setMouth(mouth);
}
////////////////////////
FInt2 nose = getNose();
if(nose == null){
nose = new FInt2();
}
nose.setX((int)this.nativeData[FD_NOSE_X.ordinal()]);
nose.setY((int)this.nativeData[FD_NOSE_Y.ordinal()]);
setNose(nose);
//////////////////////
confidence = this.nativeData[FD_CONFIDENCE.ordinal()];
setFacialData(asByteArray(this.nativeData));
}
/**
* {@link CodeInfo} 转换为{@link NativeFaceInfo}
* @param code
* @return
*/
public static NativeFaceInfo toNative(CodeInfo code){
if(code == null){
return null;
}
CodeInfo faceInfo = code instanceof NativeFaceInfo
? code
: new NativeFaceInfo(code);
return (NativeFaceInfo) faceInfo.relocate();
}
public static long getSerialversionuid() {
return serialVersionUID;
}
public double getConfidence() {
return confidence;
}
/**
* @return原始人脸检测数据 double[61]
*/
public double[] getNativeData() {
return nativeData;
}
@Override
protected void relocateFacialData() {
if(null != getOffset() && !ZERO_OFFSET.equals(getOffset()) ){
double[] ndata = this.nativeData;
if(null == ndata){
ndata = asDoubleArray(getFacialData());
}
if(null != ndata){
int ox = getOffset().getX();
int oy = getOffset().getY();
try {
ndata[FRECT_LEFT.ordinal()] -= ox;
ndata[FRECT_TOP.ordinal()] -= oy;
ndata[FD_LEFT_EYE_X.ordinal()] -= ox;
ndata[FD_LEFT_EYE_Y.ordinal()] -= oy;
ndata[FD_RIGHT_EYE_X.ordinal()] -= ox;
ndata[FD_RIGHT_EYE_Y.ordinal()] -= oy;
ndata[FD_NOSE_X.ordinal()] -= ox;
ndata[FD_NOSE_Y.ordinal()] -= oy;
ndata[FD_MOUTH_LEFT_X.ordinal()] -= ox;
ndata[FD_MOUTH_LEFT_Y.ordinal()] -= oy;
ndata[FD_MOUTH_RIGHT_X.ordinal()] -= ox;
ndata[FD_MOUTH_RIGHT_Y.ordinal()] -= oy;
} catch (IndexOutOfBoundsException e) {
// 数组访问越界则抛出异常
throw new IllegalStateException(
String.format("INVALID nativeData %d float required cased by IndexOutOfBoundsException",
FDDATA_LEN));
}
if(null != getFacialData()){
setFacialData(asByteArray(ndata));
}
}
}
}
}