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(); } } }