net.gdface.cassdk.FaceApiCas Maven / Gradle / Ivy
package net.gdface.cassdk;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Logger;
import net.gdface.cassdk.jna.FaceAngle;
import net.gdface.cassdk.jna.THFI_FacePos;
import net.gdface.cassdk.jna.tagPOINT;
import net.gdface.cassdk.jna.tagRECT;
import net.gdface.image.ImageErrorException;
import net.gdface.image.LazyImage;
import net.gdface.image.UnsupportedFormatException;
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.sdk.BaseFaceApiLocal;
import net.gdface.sdk.NotFaceDetectedException;
import net.gdface.sdk.RectUtils;
import net.gdface.utils.Assert;
import net.gdface.utils.FaceUtilitsX;
/**
* CASSDK接口实现类
*
* @author guyadong
*
*/
public class FaceApiCas extends BaseFaceApiLocal {
private static final Logger logger = Logger.getLogger(FaceApiCas.class.getSimpleName());
private static final FaceApiCas INSTANCE = new FaceApiCas();
static {
if (!FaceUtilitsX.isBuilding()) {
try {
// CASSDK JNI接口静态区初始化
Class.forName(net.gdface.cassdk.JniBridge.class.getName());
} catch (ClassNotFoundException e) {
logger.severe(e.getMessage());
throw new ExceptionInInitializerError(e);
}
}
}
private FaceApiCas() {
}
/**
* @return the instance
*/
public static FaceApiCas getInstance() {
return INSTANCE;
}
@Override
protected double doCompareCode(byte[] code1, byte[] code2) {
return (double)JniBridge.compareFeature(code1, code2);
}
/**
* 底层类型->通用类型
* @param rect
* @return FRect,rect为{@code null}时返回{@code null}
*/
static private FRect makeFRect(tagRECT rect){
return null==rect
?null
:new FRect(
rect.left
,rect.top
,rect.right-rect.left+1
,rect.bottom-rect.top+1);
}
/**
* 通用类型->底层类型
* @param rect
* @return FaceRect,rect为{@code null}时返回{@code null}
*/
private static final tagRECT toNative(FRect rect){
return null==rect
?null
:new tagRECT(
rect.getLeft()
,rect.getTop()
,rect.getLeft()+rect.getWidth()-1
,rect.getTop()+rect.getHeight()-1);
}
/**
* 底层类型->通用类型
* @param leftEye 左眼位置
* @param rightEye 右眼位置
* @return EyeInfo,leftEye或rightEye为{@code null}或所有的值为0时返回{@code null}
*/
private static final EyeInfo makeEyeInfo(tagPOINT leftEye,tagPOINT rightEye){
return null==leftEye||null==rightEye||(0==leftEye.x&&0==leftEye.y&&0==rightEye.x&&0==rightEye.y)
?null
:new EyeInfo(leftEye.x,leftEye.y,rightEye.x,rightEye.y);
}
/**
* 通用类型->底层类型
* @param ei
* @return FacePoint,ei为{@code null}或所有的值为0时返回{@code null}
*/
private static final tagPOINT toNativeLeft(EyeInfo ei){
return null==ei||(0==ei.getLeftx()&&0==ei.getLefty())
?null:new tagPOINT(ei.getLeftx(),ei.getLefty());
}
/**
* 通用类型->底层类型
* @param ei
* @return FacePoint,ei为{@code null}或所有的值为0时返回{@code null}
*/
private static final tagPOINT toNativeRight(EyeInfo ei){
return null==ei||(0==ei.getRightx()&&0==ei.getRighty())
?null:new tagPOINT(ei.getRightx(),ei.getRighty());
}
/**
* 底层类型->通用类型
* @param point
* @return FInt2,point为{@code null}或所有的值为0时返回{@code null}
*/
private static final FInt2 makeFInt2(tagPOINT point){
return null==point||(0==point.x&&0==point.y)
?null:new FInt2(point.x,point.y);
}
/**
* 通用类型->底层类型
* @param point
* @return FacePoint,point为{@code null}或所有的值为0时返回{@code null}
*/
private static final tagPOINT toNative(FInt2 point){
return null==point||(0==point.getX()&&0==point.getY())
?null:new tagPOINT(point.getX(),point.getY());
}
/**
* 底层类型->通用类型
* @param angle
* @return FAngle,angle为{@code null}或所有的值为0时返回{@code null}
*/
private static final FAngle makeFAngle(FaceAngle angle){
return null==angle||(0==angle.yaw&&0==angle.pitch&&0==angle.roll)
?null:new FAngle(angle.yaw,angle.pitch,angle.roll,angle.confidence);
}
/**
* 通用类型->底层类型
* @param angle
* @return FAngle,angle为{@code null}或所有的值为0时返回{@code null}
*/
private static final FaceAngle toNative(FAngle angle){
return null==angle||(0==angle.getYaw()&&0==angle.getPitch()&&0==angle.getRoll())
?null:new FaceAngle(angle.getYaw(),angle.getPitch(),angle.getRoll(),angle.getConfidence());
}
/**
* 底层类型->通用类型
* @param ci
* @return CodeInfo,ci为{@code null}时返回{@code null}
*/
private static final CodeInfo makeCodeInfo(THFI_FacePos ci){
return null==ci?null:
new CodeInfo(null
, makeFRect(ci.rcFace)
, makeEyeInfo(ci.ptLeftEye,ci.ptRightEye)
, makeFInt2(ci.ptMouth)
, makeFInt2(ci.ptNose)
, makeFAngle(ci.fAngle)
, ci.pFacialData);
}
/**
* 通用类型->底层类型
* @param pos
* @return FacePos,pos为{@code null}时返回{@code null}
*/
private static final THFI_FacePos toNative(CodeInfo pos){
return null==pos?null:
new THFI_FacePos(
toNative(pos.getPos())
, toNativeLeft(pos.getEi())
, toNativeRight(pos.getEi())
, toNative(pos.getMouth())
, toNative(pos.getNose())
, toNative(pos.getAngle())
, 0
, pos.getFacialData());
}
@Override
public List detectFace(LazyImage lazyImg, final FRect detectRectangle)
throws UnsupportedFormatException {
concurrentLock.lock();
try {
Assert.notNull(lazyImg, "bufImg");
// detectRectangle为空时,全图提取特征码
Rectangle imgRect = lazyImg.getRectangle();
Rectangle dr;
if (null == detectRectangle){
dr = imgRect;
}else{
// 如果指定的检测范围范围超出图像尺寸,则抛出异常
RectUtils.assertContains(imgRect, "imgRect", dr = RectUtils.newRectangle(detectRectangle),
"detectRectangle");
}
List faceInfo = new ArrayList();
if (dr.width > 0 && dr.height > 0) {
final byte[] imgRGB =getMatrixData(lazyImg, RectUtils.newFRect(dr));
THFI_FacePos[] posArray = JniBridge.detectFace(imgRGB, 24, dr.width, dr.height);
for (THFI_FacePos pos : posArray){
faceInfo.add(makeCodeInfo(pos));
}
if (!RectUtils.isZeroPoint(dr)) {
// 坐标系转换
for (CodeInfo ci : faceInfo) {
RectUtils.translate(ci, dr.x, dr.y);
}
}
}
return faceInfo;
} finally {
concurrentLock.unlock();
}
}
@Override
protected final CodeInfo getCodeFromImageMatrix(final byte[] imgMatrix, final int width, final int height,
CodeInfo faceInfo, final AtomicBoolean hasFail) {
Assert.notEmpty(imgMatrix, "imgMatrix");
if (width <= 0 || height <= 0){
throw new IllegalArgumentException(String.format("INVALID VALUE:the imgMatrix's size(%dW%dH) ", width,
height));
}
Assert.notNull(faceInfo, "faceInfo");
byte[] code = JniBridge.getFaceFeature(imgMatrix, width, height, toNative(faceInfo));
if (null==code && null != hasFail){
hasFail.set(true);
}
faceInfo.setCode(code);
return faceInfo;
}
@Override
protected byte[] getMatrixData(LazyImage lazyImg, FRect rect) throws UnsupportedFormatException {
return lazyImg.getMatrixBGR(null==rect?null:RectUtils.newRectangle(rect));
}
@Override
public List getCodeInfo(LazyImage lazyImg, int faceNum, List facePos) throws NotFaceDetectedException {
concurrentLock.lock();
// 检测到的人脸数目
int faceCount = 0;
// 提取到特征码的人脸数目
int featureCount=0;
final AtomicBoolean hasFail = new AtomicBoolean(false);
try {
Assert.notNull(lazyImg, "lazyImg");
// facePos为null或空时抛出异常
Assert.notEmpty(facePos, "facePos");
// 人脸位置对象数目小于要求提取的特征码的数目,则抛出异常
if (facePos.size() < faceNum){
throw new NotFaceDetectedException(facePos.size(), 0);
}
byte[] imgData=getMatrixData(lazyImg,null);
THFI_FacePos[] nativeArray = new THFI_FacePos[facePos.size()];
for(int i=0;i 0)) {
if (featureCount != faceNum){
throw new NotFaceDetectedException(faceCount, featureCount);
}
} else if (0 == featureCount){
throw new NotFaceDetectedException(faceCount, 0);
}
for(int i=0;i facePos = JniBridge.detectAndGetFeatures(imgData, lazyImg.getWidth(), lazyImg.getHeight());
// 没有检测到要求的人脸则抛出异常
if(0==facePos.size()){
throw NOTFACEDETECTED_INSTANCE_DEFAULT;
}
if(faceNum>0&&faceNum!=facePos.size()){
throw NOTFACEDETECTED_INSTANCE_DEFAULT;
}
CodeInfo[] ci = new CodeInfo[facePos.size()];
int i = 0;
CodeInfo element = null;
for(Entry entry:facePos.entrySet()){
element = makeCodeInfo(entry.getKey());
element.setCode(entry.getValue());
ci[ i++ ] = element;
}
return ci;
}finally{
concurrentLock.unlock();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy