using ArcFaceAPI.ArcFunction;
using ArcFaceAPI.Entity;
using ArcFaceAPI.Model;
using ArcFaceAPI.Utils;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace ArcFaceAPI
{
///
/// ArcFace 接口封装类
///
public class FaceEngine
{
///
/// 引擎 handle
///
private IntPtr pEngine;
///
/// 判断引擎状态
///
/// true:引擎已初始化;false:引擎未初始化
public bool GetEngineStatus()
{
return !(pEngine.Equals(IntPtr.Zero));
}
///
/// 激活接口
///
/// appId
/// appKey
/// 返回0表示正常;其他值请在官网-帮助中心查询
public int ASFActivation(string appId, string appKey)
{
return ASFFunctions.ASFActivation(appId, appKey);
}
///
/// 激活接口
///
/// appId
/// appKey
/// 返回0或90114表示正常;其他值请在官网-帮助中心查询
public int ASFOnlineActivation(string appId, string appKey)
{
return ASFFunctions.ASFOnlineActivation(appId, appKey);
}
///
/// 引擎初始化
///
/// 检测模式
/// 检测脸部的角度优先值
/// 用于数值化表示的最小人脸尺寸
/// 最大需要检测的人脸个数
/// 用户选择需要检测的功能组合,可单个或多个
/// 返回0表示正常;其他值请在官网-帮助中心查询
public int ASFInitEngine(DetectionMode detectMode, ASF_OrientPriority detectFaceOrientPriority, int detectFaceScaleVal, int detectFaceMaxNum, int combinedMask)
{
pEngine = IntPtr.Zero;
if (detectFaceScaleVal < 2 || detectFaceScaleVal > 32)
{
detectFaceScaleVal = 16;
}
if (detectFaceMaxNum < 1 || detectFaceMaxNum > 50)
{
detectFaceMaxNum = 10;
}
int retCode = ASFFunctions.ASFInitEngine(detectMode, detectFaceOrientPriority, detectFaceScaleVal, detectFaceMaxNum, combinedMask, ref pEngine);
return retCode;
}
///
/// 人脸检测/人脸追踪
///
/// 图片格式
/// 图片
/// 多人脸对象
/// 检测模式
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFDetectFaces(Image image, out MultiFaceInfo multiFaceInfo, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8, ASF_DetectModel detectModel = ASF_DetectModel.ASF_DETECT_MODEL_RGB)
{
multiFaceInfo = new MultiFaceInfo();
//判断图像是否为空
if (image == null)
{
return ErrorCodeUtil.IMAGE_IS_NULL;
}
ImageInfo imageInfo = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8.Equals(imageFormat) ? ImageUtil.ReadBMP(image) : ImageUtil.ReadBMP_IR(image);
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
IntPtr pMultiFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFDetectFaces(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo);
if (retCode != 0)
{
MemoryUtil.FreeArray(imageInfo.imgData, pMultiFaceInfo);
return retCode;
}
ASF_MultiFaceInfo multiFaceInfoStruct = MemoryUtil.PtrToStructure(pMultiFaceInfo);
MemoryUtil.FreeArray(imageInfo.imgData, pMultiFaceInfo);
//转化非托管内存到托管内存
multiFaceInfo.faceNum = multiFaceInfoStruct.faceNum;
if (multiFaceInfo.faceNum > 0)
{
if (multiFaceInfoStruct.faceID != IntPtr.Zero)
{
multiFaceInfo.faceID = new int[multiFaceInfo.faceNum];
Marshal.Copy(multiFaceInfoStruct.faceID, multiFaceInfo.faceID, 0, multiFaceInfo.faceNum);
}
multiFaceInfo.faceOrients = new int[multiFaceInfo.faceNum];
Marshal.Copy(multiFaceInfoStruct.faceOrients, multiFaceInfo.faceOrients, 0, multiFaceInfo.faceNum);
multiFaceInfo.faceRects = new MRECT[multiFaceInfo.faceNum];
for (int i = 0; i < multiFaceInfo.faceNum; i++)
{
multiFaceInfo.faceRects[i] = MemoryUtil.PtrToStructure(multiFaceInfoStruct.faceRects + MemoryUtil.SizeOf() * i);
}
}
return retCode;
}
///
/// 人脸信息检测(年龄/性别/人脸3D角度)
///
/// 图片格式
/// 图片
/// 多人脸对象
/// 检测属性
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFProcess(Image image, MultiFaceInfo multiFaceInfo, int combinedMask, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8)
{
if (multiFaceInfo == null)
{
return ErrorCodeUtil.MULPTIFACEINFO_IS_NULL;
}
if (image == null)
{
return ErrorCodeUtil.IMAGE_IS_NULL;
}
ImageInfo imageInfo = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8.Equals(imageFormat) ? ImageUtil.ReadBMP(image) : ImageUtil.ReadBMP_IR(image);
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
//将多人脸对象的信息转化到结构体中
ASF_MultiFaceInfo multiFaceInfoStruct = new ASF_MultiFaceInfo();
IntPtr pMultiFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
multiFaceInfoStruct.faceNum = multiFaceInfo.faceNum;
if (multiFaceInfo.faceNum > 0)
{
if (multiFaceInfo.faceID != null)
{
multiFaceInfoStruct.faceID = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceID, 0, multiFaceInfoStruct.faceID, multiFaceInfo.faceNum);
}
multiFaceInfoStruct.faceOrients = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceOrients, 0, multiFaceInfoStruct.faceOrients, multiFaceInfo.faceNum);
multiFaceInfoStruct.faceRects = MemoryUtil.Malloc(MemoryUtil.SizeOf() * multiFaceInfo.faceNum);
byte[] allByte = new byte[MemoryUtil.SizeOf() * multiFaceInfo.faceNum];
for (int i = 0; i < multiFaceInfo.faceNum; i++)
{
byte[] tempBytes = MemoryUtil.StructToBytes(multiFaceInfo.faceRects[i]);
tempBytes.CopyTo(allByte, MemoryUtil.SizeOf() * i);
}
Marshal.Copy(allByte, 0, multiFaceInfoStruct.faceRects, allByte.Length);
}
MemoryUtil.StructureToPtr(multiFaceInfoStruct, pMultiFaceInfo);
//调用SDK接口
int retCode = ASFFunctions.ASFProcess(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, combinedMask);
//释放内存
MemoryUtil.FreeArray(imageInfo.imgData, multiFaceInfoStruct.faceID, multiFaceInfoStruct.faceOrients, multiFaceInfoStruct.faceRects, pMultiFaceInfo);
return retCode;
}
///
/// 单人脸特征提取
///
/// 图片格式
/// 图片
/// 人脸框对象
/// 人脸索引
/// [out]特征结果
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFFaceFeatureExtract(Image image, MultiFaceInfo multiFaceInfo, out FaceFeature faceFeature, int faceIndex = 0, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8)
{
faceFeature = new FaceFeature();
if (multiFaceInfo == null)
{
return ErrorCodeUtil.MULPTIFACEINFO_IS_NULL;
}
if (faceIndex >= multiFaceInfo.faceNum)
{
return ErrorCodeUtil.FACEINDEX_INVALID;
}
if (image == null)
{
return ErrorCodeUtil.IMAGE_IS_NULL;
}
ImageInfo imageInfo = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8.Equals(imageFormat) ? ImageUtil.ReadBMP(image) : ImageUtil.ReadBMP_IR(image);
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
//获取某个单人脸信息
SingleFaceInfo singleFaceInfo = new SingleFaceInfo();
IntPtr pSIngleFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
singleFaceInfo.faceRect = multiFaceInfo.faceRects[faceIndex];
singleFaceInfo.faceOrient = multiFaceInfo.faceOrients[faceIndex];
MemoryUtil.StructureToPtr(singleFaceInfo, pSIngleFaceInfo);
IntPtr pAsfFaceFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFFaceFeatureExtract(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pSIngleFaceInfo, pAsfFaceFeature);
if (retCode != 0)
{
MemoryUtil.FreeArray(pSIngleFaceInfo, pAsfFaceFeature, imageInfo.imgData);
return retCode;
}
//获取特征结构体,并转化
ASF_FaceFeature asfFeature = MemoryUtil.PtrToStructure(pAsfFaceFeature);
byte[] feature = new byte[asfFeature.featureSize];
MemoryUtil.Copy(asfFeature.feature, feature, 0, asfFeature.featureSize);
faceFeature.featureSize = asfFeature.featureSize;
faceFeature.feature = feature;
MemoryUtil.FreeArray(pSIngleFaceInfo, pAsfFaceFeature, imageInfo.imgData);
return retCode;
}
///
/// 人脸特征比对
///
/// 特征1
/// 特征2
/// 相似度
/// ASF_LIFE_PHOTO:用于生活照之间的特征比对;ASF_ID_PHOTO:用于证件照或证件照和生活照之间的特征比对
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFFaceFeatureCompare(FaceFeature faceFeature1, FaceFeature faceFeature2, out float similarity, ASF_CompareModel compareModel = ASF_CompareModel.ASF_LIFE_PHOTO)
{
similarity = 0f;
if (faceFeature1 == null || faceFeature2 == null)
{
return ErrorCodeUtil.FEATURE_IS_NULL;
}
#region 将特征对象转化为特征结构体,再转化为非托管内存
ASF_FaceFeature asfFeatureStruct1 = new ASF_FaceFeature();
asfFeatureStruct1.featureSize = faceFeature1.featureSize;
asfFeatureStruct1.feature = MemoryUtil.Malloc(asfFeatureStruct1.featureSize);
MemoryUtil.Copy(faceFeature1.feature, 0, asfFeatureStruct1.feature, asfFeatureStruct1.featureSize);
IntPtr pFeature1 = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(asfFeatureStruct1, pFeature1);
ASF_FaceFeature asfFeatureStruct2 = new ASF_FaceFeature();
asfFeatureStruct2.featureSize = faceFeature2.featureSize;
asfFeatureStruct2.feature = MemoryUtil.Malloc(asfFeatureStruct2.featureSize);
MemoryUtil.Copy(faceFeature2.feature, 0, asfFeatureStruct2.feature, asfFeatureStruct2.featureSize);
IntPtr pFeature2 = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(asfFeatureStruct2, pFeature2);
#endregion
//调用SDK接口
int retCode = ASFFunctions.ASFFaceFeatureCompare(pEngine, pFeature1, pFeature2, ref similarity, compareModel);
MemoryUtil.FreeArray(pFeature1, pFeature2, asfFeatureStruct1.feature, asfFeatureStruct2.feature);
return retCode;
}
///
/// 获取年龄结果
///
/// 引擎handle
/// out 年龄结果
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFGetAge(out AgeInfo ageInfo)
{
ageInfo = new AgeInfo();
IntPtr pAgeInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFGetAge(pEngine, pAgeInfo);
if (retCode != 0)
{
MemoryUtil.Free(pAgeInfo);
return retCode;
}
//转化结果
ASF_AgeInfo asfAgeInfo = MemoryUtil.PtrToStructure(pAgeInfo);
ageInfo.num = asfAgeInfo.num;
if (ageInfo.num > 0)
{
ageInfo.ageArray = new int[ageInfo.num];
Marshal.Copy(asfAgeInfo.ageArray, ageInfo.ageArray, 0, ageInfo.num);
}
MemoryUtil.FreeArray(pAgeInfo);
return retCode;
}
///
/// 获取性别结果
///
/// 引擎handle
/// out 性别结果
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFGetGender(out GenderInfo genderInfo)
{
genderInfo = new GenderInfo();
IntPtr pGenderInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFGetGender(pEngine, pGenderInfo);
if (retCode != 0)
{
MemoryUtil.Free(pGenderInfo);
return retCode;
}
//转化结果
ASF_GenderInfo asfGenderInfo = MemoryUtil.PtrToStructure(pGenderInfo);
genderInfo.num = asfGenderInfo.num;
if (genderInfo.num > 0)
{
genderInfo.genderArray = new int[genderInfo.num];
Marshal.Copy(asfGenderInfo.genderArray, genderInfo.genderArray, 0, genderInfo.num);
}
MemoryUtil.FreeArray(pGenderInfo);
return retCode;
}
///
/// 获取3D角度信息
///
/// 引擎handle
/// 3D角度信息结果
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFGetFace3DAngle(out Face3DAngle faceAngle)
{
faceAngle = new Face3DAngle();
IntPtr pFaceAngle = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFGetFace3DAngle(pEngine, pFaceAngle);
if (retCode != 0)
{
MemoryUtil.Free(pFaceAngle);
return retCode;
}
//转化结果
ASF_Face3DAngle asfFaceAngle = MemoryUtil.PtrToStructure(pFaceAngle);
faceAngle.num = asfFaceAngle.num;
if (faceAngle.num > 0)
{
faceAngle.pitch = new float[faceAngle.num];
Marshal.Copy(asfFaceAngle.pitch, faceAngle.pitch, 0, faceAngle.num);
faceAngle.roll = new float[faceAngle.num];
Marshal.Copy(asfFaceAngle.roll, faceAngle.roll, 0, faceAngle.num);
faceAngle.yaw = new float[faceAngle.num];
Marshal.Copy(asfFaceAngle.yaw, faceAngle.yaw, 0, faceAngle.num);
faceAngle.status = new int[faceAngle.num];
Marshal.Copy(asfFaceAngle.status, faceAngle.status, 0, faceAngle.num);
}
MemoryUtil.FreeArray(pFaceAngle);
return retCode;
}
///
/// 获取RGB活体结果
///
/// 引擎handle
/// RGB活体结果
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFGetLivenessScore(out LivenessInfo livenessInfo)
{
livenessInfo = new LivenessInfo();
IntPtr pLiveness = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFGetLivenessScore(pEngine, pLiveness);
if (retCode != 0)
{
MemoryUtil.Free(pLiveness);
return retCode;
}
//转化结果
ASF_LivenessInfo asfLivenessInfo = MemoryUtil.PtrToStructure(pLiveness);
livenessInfo.num = asfLivenessInfo.num;
if (asfLivenessInfo.num > 0)
{
livenessInfo.isLive = new int[asfLivenessInfo.num];
Marshal.Copy(asfLivenessInfo.isLive, livenessInfo.isLive, 0, asfLivenessInfo.num);
}
MemoryUtil.FreeArray(pLiveness);
return retCode;
}
///
/// 该接口目前仅支持单人脸IR活体检测(不支持年龄、性别、3D角度的检测),默认取第一张人脸
///
/// 引擎handle
/// 图像格式
/// 图片
/// 人脸框信息
/// 检测属性
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFProcess_IR(Image image, MultiFaceInfo multiFaceInfo, int combinedMask, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_GRAY)
{
if (multiFaceInfo == null)
{
return ErrorCodeUtil.MULPTIFACEINFO_IS_NULL;
}
if (image == null)
{
return ErrorCodeUtil.IMAGE_IS_NULL;
}
ImageInfo imageInfo = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8.Equals(imageFormat) ? ImageUtil.ReadBMP(image) : ImageUtil.ReadBMP_IR(image);
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
//转化多人脸信息
ASF_MultiFaceInfo multiFaceInfoStruct = new ASF_MultiFaceInfo();
IntPtr pMultiFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
multiFaceInfoStruct.faceNum = multiFaceInfo.faceNum;
if (multiFaceInfo.faceNum > 0)
{
if (multiFaceInfo.faceID != null)
{
multiFaceInfoStruct.faceID = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceID, 0, multiFaceInfoStruct.faceID, multiFaceInfo.faceNum);
}
multiFaceInfoStruct.faceOrients = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceOrients, 0, multiFaceInfoStruct.faceOrients, multiFaceInfo.faceNum);
multiFaceInfoStruct.faceRects = MemoryUtil.Malloc(MemoryUtil.SizeOf() * multiFaceInfo.faceNum);
byte[] allByte = new byte[MemoryUtil.SizeOf() * multiFaceInfo.faceNum];
for (int i = 0; i < multiFaceInfo.faceNum; i++)
{
byte[] tempBytes = MemoryUtil.StructToBytes(multiFaceInfo.faceRects[i]);
tempBytes.CopyTo(allByte, MemoryUtil.SizeOf() * i);
}
Marshal.Copy(allByte, 0, multiFaceInfoStruct.faceRects, allByte.Length);
}
MemoryUtil.StructureToPtr(multiFaceInfoStruct, pMultiFaceInfo);
//调用SDK接口
int retCode = ASFFunctions.ASFProcess_IR(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, combinedMask);
//释放内存
MemoryUtil.FreeArray(multiFaceInfoStruct.faceID, multiFaceInfoStruct.faceOrients, multiFaceInfoStruct.faceRects, pMultiFaceInfo);
return retCode;
}
///
/// 获取IR活体结果
///
/// IR活体结果
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFGetLivenessScore_IR(out LivenessInfo livenessInfo)
{
livenessInfo = new LivenessInfo();
IntPtr pLiveness = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFGetLivenessScore_IR(pEngine, pLiveness);
if (retCode != 0)
{
MemoryUtil.Free(pLiveness);
return retCode;
}
//转化结果
ASF_LivenessInfo asfLivenessInfo = MemoryUtil.PtrToStructure(pLiveness);
livenessInfo.num = asfLivenessInfo.num;
if (asfLivenessInfo.num > 0)
{
livenessInfo.isLive = new int[asfLivenessInfo.num];
Marshal.Copy(asfLivenessInfo.isLive, livenessInfo.isLive, 0, asfLivenessInfo.num);
}
MemoryUtil.FreeArray(pLiveness);
return retCode;
}
///
/// 销毁引擎
///
/// 引擎handle
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public void ASFUninitEngine()
{
try
{
if (!pEngine.Equals(IntPtr.Zero))
{
ASFFunctions.ASFUninitEngine(pEngine);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
///
/// 获取版本信息
///
/// 版本信息
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFGetVersion(out SDKVersion version)
{
version = new SDKVersion();
int retCode = -1;
ASF_VERSION asfVersion = ASFFunctions.ASFGetVersion();
version.version = Marshal.PtrToStringAnsi(asfVersion.Version);
version.buildDate = Marshal.PtrToStringAnsi(asfVersion.BuildDate);
version.copyRight = Marshal.PtrToStringAnsi(asfVersion.CopyRight);
return retCode;
}
///
/// 获取激活文件信息
///
/// 激活文件信息
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFGetActiveFileInfo(out ActiveFileInfo activeFileInfo)
{
activeFileInfo = new ActiveFileInfo();
IntPtr pASFActiveFileInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFGetActiveFileInfo(pASFActiveFileInfo);
if (retCode != 0)
{
MemoryUtil.Free(pASFActiveFileInfo);
return retCode;
}
//转化结果
ASF_ActiveFileInfo asfActiveFileInfo = MemoryUtil.PtrToStructure(pASFActiveFileInfo);
activeFileInfo.startTime = Marshal.PtrToStringAnsi(asfActiveFileInfo.startTime);
activeFileInfo.endTime = Marshal.PtrToStringAnsi(asfActiveFileInfo.endTime);
activeFileInfo.platform = Marshal.PtrToStringAnsi(asfActiveFileInfo.platform);
activeFileInfo.sdkType = Marshal.PtrToStringAnsi(asfActiveFileInfo.sdkType);
activeFileInfo.appId = Marshal.PtrToStringAnsi(asfActiveFileInfo.appId);
activeFileInfo.sdkKey = Marshal.PtrToStringAnsi(asfActiveFileInfo.sdkKey);
activeFileInfo.sdkVersion = Marshal.PtrToStringAnsi(asfActiveFileInfo.sdkVersion);
activeFileInfo.fileVersion = Marshal.PtrToStringAnsi(asfActiveFileInfo.fileVersion);
MemoryUtil.Free(pASFActiveFileInfo);
return retCode;
}
///
/// 设置活体阈值:取值范围[0-1]内部默认数值RGB-0.5,IR-0.7, 用户可以根据实际需求,设置不同的阈值
///
/// RGB活体阈值
/// IR活体阈值
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFSetLivenessParam(float rgbThreshold = 0.5f, float irThreshole = 0.7f)
{
ASF_LivenessThreshold livebessThreshold = new ASF_LivenessThreshold();
//对应设置阈值
livebessThreshold.thresholdmodel_BGR = (rgbThreshold >= 0 && rgbThreshold <= 1) ? rgbThreshold : 0.5f;
livebessThreshold.thresholdmodel_IR = (irThreshole >= 0 && irThreshole <= 1) ? irThreshole : 0.7f;
IntPtr pLivenessThreshold = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(livebessThreshold, pLivenessThreshold);
//调用SDK接口
int retCode = ASFFunctions.ASFSetLivenessParam(pEngine, pLivenessThreshold);
MemoryUtil.Free(pLivenessThreshold);
return retCode;
}
///
/// 人脸检测/人脸追踪
/// 图像数据以结构体形式传入,对采用更高字节对齐方式的图像兼容性更好
///
/// 图片格式
/// 图片
/// 多人脸对象
/// 检测模式
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFDetectFacesEx(Image image, out MultiFaceInfo multiFaceInfo, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8, ASF_DetectModel detectModel = ASF_DetectModel.ASF_DETECT_MODEL_RGB)
{
multiFaceInfo = new MultiFaceInfo();
if (image == null)
{
return ErrorCodeUtil.IMAGE_IS_NULL;
}
ImageInfo imageInfo = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8.Equals(imageFormat) ? ImageUtil.ReadBMP(image) : ImageUtil.ReadBMP_IR(image);
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
ASF_ImageData asfInfoData = CommonUtil.TransImageDataStructByImageInfo(imageInfo);
IntPtr pImageInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(asfInfoData, pImageInfo);
IntPtr pMultiFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFDetectFacesEx(pEngine, pImageInfo, pMultiFaceInfo);
if (retCode != 0)
{
MemoryUtil.FreeArray(imageInfo.imgData, pMultiFaceInfo, pImageInfo);
return retCode;
}
ASF_MultiFaceInfo multiFaceInfoStruct = MemoryUtil.PtrToStructure(pMultiFaceInfo);
MemoryUtil.FreeArray(imageInfo.imgData, pMultiFaceInfo, pImageInfo);
//转化非托管内存到托管内存
multiFaceInfo.faceNum = multiFaceInfoStruct.faceNum;
if (multiFaceInfo.faceNum > 0)
{
if (multiFaceInfoStruct.faceID != IntPtr.Zero)
{
multiFaceInfo.faceID = new int[multiFaceInfo.faceNum];
Marshal.Copy(multiFaceInfoStruct.faceID, multiFaceInfo.faceID, 0, multiFaceInfo.faceNum);
}
multiFaceInfo.faceOrients = new int[multiFaceInfo.faceNum];
Marshal.Copy(multiFaceInfoStruct.faceOrients, multiFaceInfo.faceOrients, 0, multiFaceInfo.faceNum);
multiFaceInfo.faceRects = new MRECT[multiFaceInfo.faceNum];
for (int i = 0; i < multiFaceInfo.faceNum; i++)
{
multiFaceInfo.faceRects[i] = MemoryUtil.PtrToStructure(multiFaceInfoStruct.faceRects + MemoryUtil.SizeOf() * i);
}
}
return retCode;
}
///
/// 人脸检测/人脸追踪
/// 图像数据以结构体形式传入,对采用更高字节对齐方式的图像兼容性更好
///
/// 图片格式
///
/// 多人脸对象
/// 检测模式
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFDetectFacesEx(ImageInfo imageInfo, out MultiFaceInfo multiFaceInfo, ASF_DetectModel detectModel = ASF_DetectModel.ASF_DETECT_MODEL_RGB)
{
multiFaceInfo = new MultiFaceInfo();
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
ASF_ImageData asfInfoData = CommonUtil.TransImageDataStructByImageInfo(imageInfo);
IntPtr pImageInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(asfInfoData, pImageInfo);
IntPtr pMultiFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
//调用SDK接口
int retCode = ASFFunctions.ASFDetectFacesEx(pEngine, pImageInfo, pMultiFaceInfo);
if (retCode != 0)
{
MemoryUtil.FreeArray(imageInfo.imgData, pMultiFaceInfo, pImageInfo);
return retCode;
}
ASF_MultiFaceInfo multiFaceInfoStruct = MemoryUtil.PtrToStructure(pMultiFaceInfo);
MemoryUtil.FreeArray(imageInfo.imgData, pMultiFaceInfo, pImageInfo);
//转化非托管内存到托管内存
multiFaceInfo.faceNum = multiFaceInfoStruct.faceNum;
if (multiFaceInfo.faceNum > 0)
{
if (multiFaceInfoStruct.faceID != IntPtr.Zero)
{
multiFaceInfo.faceID = new int[multiFaceInfo.faceNum];
Marshal.Copy(multiFaceInfoStruct.faceID, multiFaceInfo.faceID, 0, multiFaceInfo.faceNum);
}
multiFaceInfo.faceOrients = new int[multiFaceInfo.faceNum];
Marshal.Copy(multiFaceInfoStruct.faceOrients, multiFaceInfo.faceOrients, 0, multiFaceInfo.faceNum);
multiFaceInfo.faceRects = new MRECT[multiFaceInfo.faceNum];
for (int i = 0; i < multiFaceInfo.faceNum; i++)
{
multiFaceInfo.faceRects[i] = MemoryUtil.PtrToStructure(multiFaceInfoStruct.faceRects + MemoryUtil.SizeOf() * i);
}
}
return retCode;
}
///
/// 年龄/性别/人脸3D角度(该接口仅支持RGB图像),最多支持4张人脸信息检测,超过部分返回未知
/// RGB活体仅支持单人脸检测,该接口不支持检测IR活体
///
/// 图片格式
/// 图片
/// 多人脸对象
/// 检测属性
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFProcessEx(Image image, MultiFaceInfo multiFaceInfo, int combinedMask, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8)
{
if (multiFaceInfo == null)
{
return ErrorCodeUtil.MULPTIFACEINFO_IS_NULL;
}
if (image == null)
{
return ErrorCodeUtil.IMAGE_IS_NULL;
}
ImageInfo imageInfo = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8.Equals(imageFormat) ? ImageUtil.ReadBMP(image) : ImageUtil.ReadBMP_IR(image);
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
//转化人脸信息
ASF_MultiFaceInfo multiFaceInfoStruct = new ASF_MultiFaceInfo();
IntPtr pMultiFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
multiFaceInfoStruct.faceNum = multiFaceInfo.faceNum;
if (multiFaceInfo.faceNum > 0)
{
if (multiFaceInfo.faceID != null)
{
multiFaceInfoStruct.faceID = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceID, 0, multiFaceInfoStruct.faceID, multiFaceInfo.faceNum);
}
multiFaceInfoStruct.faceOrients = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceOrients, 0, multiFaceInfoStruct.faceOrients, multiFaceInfo.faceNum);
multiFaceInfoStruct.faceRects = MemoryUtil.Malloc(MemoryUtil.SizeOf() * multiFaceInfo.faceNum);
byte[] allByte = new byte[MemoryUtil.SizeOf() * multiFaceInfo.faceNum];
for (int i = 0; i < multiFaceInfo.faceNum; i++)
{
byte[] tempBytes = MemoryUtil.StructToBytes(multiFaceInfo.faceRects[i]);
tempBytes.CopyTo(allByte, MemoryUtil.SizeOf() * i);
}
Marshal.Copy(allByte, 0, multiFaceInfoStruct.faceRects, allByte.Length);
}
MemoryUtil.StructureToPtr(multiFaceInfoStruct, pMultiFaceInfo);
ASF_ImageData asfInfoData = CommonUtil.TransImageDataStructByImageInfo(imageInfo);
IntPtr pImageInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(asfInfoData, pImageInfo);
//调用SDK接口
int retCode = ASFFunctions.ASFProcessEx(pEngine, pImageInfo, pMultiFaceInfo, combinedMask);
//释放内存
MemoryUtil.FreeArray(imageInfo.imgData, multiFaceInfoStruct.faceID, multiFaceInfoStruct.faceOrients, multiFaceInfoStruct.faceRects, pMultiFaceInfo, pImageInfo);
return retCode;
}
///
/// 年龄/性别/人脸3D角度(该接口仅支持RGB图像),最多支持4张人脸信息检测,超过部分返回未知
/// RGB活体仅支持单人脸检测,该接口不支持检测IR活体
///
/// 图片格式
/// 图片
/// 多人脸对象
/// 检测属性
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFProcessEx(ImageInfo imageInfo, MultiFaceInfo multiFaceInfo, int combinedMask, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8)
{
//转化人脸信息
ASF_MultiFaceInfo multiFaceInfoStruct = new ASF_MultiFaceInfo();
IntPtr pMultiFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
multiFaceInfoStruct.faceNum = multiFaceInfo.faceNum;
if (multiFaceInfo.faceNum > 0)
{
if (multiFaceInfo.faceID != null)
{
multiFaceInfoStruct.faceID = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceID, 0, multiFaceInfoStruct.faceID, multiFaceInfo.faceNum);
}
multiFaceInfoStruct.faceOrients = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceOrients, 0, multiFaceInfoStruct.faceOrients, multiFaceInfo.faceNum);
multiFaceInfoStruct.faceRects = MemoryUtil.Malloc(MemoryUtil.SizeOf() * multiFaceInfo.faceNum);
byte[] allByte = new byte[MemoryUtil.SizeOf() * multiFaceInfo.faceNum];
for (int i = 0; i < multiFaceInfo.faceNum; i++)
{
byte[] tempBytes = MemoryUtil.StructToBytes(multiFaceInfo.faceRects[i]);
tempBytes.CopyTo(allByte, MemoryUtil.SizeOf() * i);
}
Marshal.Copy(allByte, 0, multiFaceInfoStruct.faceRects, allByte.Length);
}
MemoryUtil.StructureToPtr(multiFaceInfoStruct, pMultiFaceInfo);
ASF_ImageData asfInfoData = CommonUtil.TransImageDataStructByImageInfo(imageInfo);
IntPtr pImageInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(asfInfoData, pImageInfo);
//调用SDK接口
int retCode = ASFFunctions.ASFProcessEx(pEngine, pImageInfo, pMultiFaceInfo, combinedMask);
//释放内存
MemoryUtil.FreeArray(imageInfo.imgData, multiFaceInfoStruct.faceID, multiFaceInfoStruct.faceOrients, multiFaceInfoStruct.faceRects, pMultiFaceInfo, pImageInfo);
return retCode;
}
///
/// 该接口目前仅支持单人脸IR活体检测(不支持年龄、性别、3D角度的检测),默认取第一张人脸
/// 图像数据以结构体形式传入,对采用更高字节对齐方式的图像兼容性更好
///
/// 图像格式
/// 图片
/// 人脸框信息
/// 检测属性
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFProcessEx_IR(Image image, MultiFaceInfo multiFaceInfo, int combinedMask, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_GRAY)
{
if (multiFaceInfo == null)
{
return ErrorCodeUtil.MULPTIFACEINFO_IS_NULL;
}
if (image == null)
{
return ErrorCodeUtil.IMAGE_IS_NULL;
}
ImageInfo imageInfo = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8.Equals(imageFormat) ? ImageUtil.ReadBMP(image) : ImageUtil.ReadBMP_IR(image);
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
//转化人脸信息
ASF_MultiFaceInfo multiFaceInfoStruct = new ASF_MultiFaceInfo();
IntPtr pMultiFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
multiFaceInfoStruct.faceNum = multiFaceInfo.faceNum;
if (multiFaceInfo.faceNum > 0)
{
if (multiFaceInfo.faceID != null)
{
multiFaceInfoStruct.faceID = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceID, 0, multiFaceInfoStruct.faceID, multiFaceInfo.faceNum);
}
multiFaceInfoStruct.faceOrients = MemoryUtil.Malloc(multiFaceInfo.faceNum * MemoryUtil.SizeOf());
Marshal.Copy(multiFaceInfo.faceOrients, 0, multiFaceInfoStruct.faceOrients, multiFaceInfo.faceNum);
multiFaceInfoStruct.faceRects = MemoryUtil.Malloc(MemoryUtil.SizeOf() * multiFaceInfo.faceNum);
byte[] allByte = new byte[MemoryUtil.SizeOf() * multiFaceInfo.faceNum];
for (int i = 0; i < multiFaceInfo.faceNum; i++)
{
byte[] tempBytes = MemoryUtil.StructToBytes(multiFaceInfo.faceRects[i]);
tempBytes.CopyTo(allByte, MemoryUtil.SizeOf() * i);
}
Marshal.Copy(allByte, 0, multiFaceInfoStruct.faceRects, allByte.Length);
}
MemoryUtil.StructureToPtr(multiFaceInfoStruct, pMultiFaceInfo);
ASF_ImageData asfInfoData = CommonUtil.TransImageDataStructByImageInfo(imageInfo);
IntPtr pImageInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(asfInfoData, pImageInfo);
//调用SDK接口
int retCode = ASFFunctions.ASFProcessEx_IR(pEngine, pImageInfo, pMultiFaceInfo, combinedMask);
//释放内存
MemoryUtil.FreeArray(imageInfo.imgData, multiFaceInfoStruct.faceID, multiFaceInfoStruct.faceOrients, multiFaceInfoStruct.faceRects, pMultiFaceInfo, pImageInfo);
return retCode;
}
///
/// 单人脸特征提取
///
/// 图片格式
/// 图片
/// 人脸框对象
/// 人脸索引
/// [out]特征结果
/// 返回0表示正常;返回负数请根据ErrorCodeUtil类注释查看;其他值请在官网-帮助中心查询
public int ASFFaceFeatureExtractEx(Image image, MultiFaceInfo multiFaceInfo, out FaceFeature faceFeature, int faceIndex = 0, ASF_ImagePixelFormat imageFormat = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8)
{
faceFeature = new FaceFeature();
if (multiFaceInfo == null)
{
return ErrorCodeUtil.MULPTIFACEINFO_IS_NULL;
}
if (faceIndex >= multiFaceInfo.faceNum)
{
return ErrorCodeUtil.FACEINDEX_INVALID;
}
if (image == null)
{
return ErrorCodeUtil.IMAGE_IS_NULL;
}
ImageInfo imageInfo = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8.Equals(imageFormat) ? ImageUtil.ReadBMP(image) : ImageUtil.ReadBMP_IR(image);
if (imageInfo == null)
{
return ErrorCodeUtil.IMAGE_DATA_READ_FAIL;
}
//转化单人脸信息
SingleFaceInfo singleFaceInfo = new SingleFaceInfo();
IntPtr pSIngleFaceInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
singleFaceInfo.faceRect = multiFaceInfo.faceRects[faceIndex];
singleFaceInfo.faceOrient = multiFaceInfo.faceOrients[faceIndex];
MemoryUtil.StructureToPtr(singleFaceInfo, pSIngleFaceInfo);
IntPtr pAsfFaceFeature = MemoryUtil.Malloc(MemoryUtil.SizeOf());
ASF_ImageData asfInfoData = CommonUtil.TransImageDataStructByImageInfo(imageInfo);
IntPtr pImageInfo = MemoryUtil.Malloc(MemoryUtil.SizeOf());
MemoryUtil.StructureToPtr(asfInfoData, pImageInfo);
//调用SDK接口
int retCode = ASFFunctions.ASFFaceFeatureExtractEx(pEngine, pImageInfo, pSIngleFaceInfo, pAsfFaceFeature);
if (retCode != 0)
{
MemoryUtil.FreeArray(pSIngleFaceInfo, pAsfFaceFeature, imageInfo.imgData, pImageInfo);
return retCode;
}
ASF_FaceFeature asfFeature = MemoryUtil.PtrToStructure(pAsfFaceFeature);
byte[] feature = new byte[asfFeature.featureSize];
MemoryUtil.Copy(asfFeature.feature, feature, 0, asfFeature.featureSize);
faceFeature.featureSize = asfFeature.featureSize;
faceFeature.feature = feature;
MemoryUtil.FreeArray(pSIngleFaceInfo, pAsfFaceFeature, imageInfo.imgData, pImageInfo);
return retCode;
}
///
/// 析构函数-注销引擎
///
~FaceEngine()
{
ASFUninitEngine();
}
}
}