/// <summary> /// 性别检测 /// </summary> /// <param name="pEngine">引擎Handle</param> /// <param name="imageInfo">图像数据</param> /// <param name="multiFaceInfo">人脸检测结果</param> /// <returns>保存性别估计结果结构体</returns> public static ASF_GenderInfo GenderEstimation(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo) { IntPtr pMultiFaceInfo = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_MultiFaceInfo>()); MemoryHelper.StructureToPtr(multiFaceInfo, pMultiFaceInfo); if (multiFaceInfo.faceNum == 0) { return(new ASF_GenderInfo()); } //人脸信息处理 int retCode = ASFWrapper.ASFProcess(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, FaceEngineMask.ASF_GENDER); //获取性别信息 IntPtr pGenderInfo = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_GenderInfo>()); retCode = ASFWrapper.ASFGetGender(pEngine, pGenderInfo); //Console.WriteLine("Get Gender Result:" + retCode); SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.FaceProcessHelper), $"Get Gender Result:{retCode}"); ASF_GenderInfo genderInfo = MemoryHelper.PtrToStructure <ASF_GenderInfo>(pGenderInfo); //释放内存 MemoryHelper.Free(pMultiFaceInfo); MemoryHelper.Free(pGenderInfo); return(genderInfo); }
/// <summary> /// 用矩形框标记图片指定区域 /// </summary> /// <param name="image">图片</param> /// <param name="startX">矩形框左上角X坐标</param> /// <param name="startY">矩形框左上角Y坐标</param> /// <param name="width">矩形框宽度</param> /// <param name="height">矩形框高度</param> /// <returns>标记后的图片</returns> public static Image MarkRect(Image image, int startX, int startY, int width, int height) { Image clone = (Image)image.Clone(); Graphics g = Graphics.FromImage(clone); try { Brush brush = new SolidBrush(Color.DeepPink); Pen pen = new Pen(brush, 2); pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash; g.DrawRectangle(pen, new Rectangle(startX, startY, width, height)); return(clone); } catch (Exception e) { //Console.WriteLine(e.Message); SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.ImageHelper), e.ToString()); } finally { g.Dispose(); } return(null); }
/// <summary> /// 年龄检测 /// </summary> /// <param name="pEngine">引擎Handle</param> /// <param name="imageInfo">图像数据</param> /// <param name="multiFaceInfo">人脸检测结果</param> /// <returns>年龄检测结构体</returns> public static ASF_AgeInfo AgeEstimation(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo, out int retCode) { retCode = -1; IntPtr pMultiFaceInfo = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_MultiFaceInfo>()); MemoryHelper.StructureToPtr(multiFaceInfo, pMultiFaceInfo); if (multiFaceInfo.faceNum == 0) { return(new ASF_AgeInfo()); } //人脸信息处理 retCode = ASFWrapper.ASFProcess(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, FaceEngineMask.ASF_AGE); if (retCode == 0) { //获取年龄信息 IntPtr pAgeInfo = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_AgeInfo>()); retCode = ASFWrapper.ASFGetAge(pEngine, pAgeInfo); //Console.WriteLine("Get Age Result:" + retCode); SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.FaceProcessHelper), $"Get Age Result:{retCode}"); ASF_AgeInfo ageInfo = MemoryHelper.PtrToStructure <ASF_AgeInfo>(pAgeInfo); //释放内存 MemoryHelper.Free(pMultiFaceInfo); MemoryHelper.Free(pAgeInfo); return(ageInfo); } else { return(new ASF_AgeInfo()); } }
/// <summary> /// RGB活体检测 /// </summary> /// <param name="pEngine"></param> /// <param name="imageInfo"></param> /// <param name="multiFaceInfo"></param> /// <returns></returns> public static ASF_LivenessInfo LivenessEstimation(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo) { IntPtr pMultiFaceInfo = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_MultiFaceInfo>()); MemoryHelper.StructureToPtr(multiFaceInfo, pMultiFaceInfo); try { if (multiFaceInfo.faceNum == 0) { return(new ASF_LivenessInfo()); } if (multiFaceInfo.faceNum > 1) { ASF_SingleFaceInfo singleFaceInfo = GetMaxFace(multiFaceInfo); ASF_MultiFaceInfo multiFaceInfoNeo = new ASF_MultiFaceInfo(); multiFaceInfoNeo.faceRects = MemoryHelper.Malloc(MemoryHelper.SizeOf <MRECT>()); MemoryHelper.StructureToPtr <MRECT>(singleFaceInfo.faceRect, multiFaceInfoNeo.faceRects); multiFaceInfoNeo.faceOrients = MemoryHelper.Malloc(MemoryHelper.SizeOf <int>()); MemoryHelper.StructureToPtr <int>(singleFaceInfo.faceOrient, multiFaceInfoNeo.faceOrients); multiFaceInfoNeo.faceNum = 1; MemoryHelper.StructureToPtr(multiFaceInfoNeo, pMultiFaceInfo); } //活体信息检测 int retCode = ASFWrapper.ASFProcess(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, FaceEngineMask.ASF_LIVENESS); if (retCode == 0) { //获取活体信息 IntPtr pLivenessInfo = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_LivenessInfo>()); retCode = ASFWrapper.ASFGetLivenessScore(pEngine, pLivenessInfo); SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.FaceProcessHelper), $"Get Liveness Result:{retCode}"); ASF_LivenessInfo livenessInfo = MemoryHelper.PtrToStructure <ASF_LivenessInfo>(pLivenessInfo); //释放内存 MemoryHelper.Free(pLivenessInfo); return(livenessInfo); } else { return(new ASF_LivenessInfo()); } } catch (Exception ex) { Afw.Core.Helper.SimplifiedLogHelper.WriteIntoSystemLog(nameof(FaceProcessHelper), $"LivenessEstimation Exception => {ex.ToString()}"); } finally { //释放内存 MemoryHelper.Free(pMultiFaceInfo); MemoryHelper.Free(imageInfo.imgData); } return(new ASF_LivenessInfo()); }
/// <summary> /// 获取图片信息 /// </summary> /// <param name="image">图片</param> /// <returns>成功或失败</returns> public static ImageInfo ReadBMP(Image image) { ImageInfo imageInfo = new ImageInfo(); //将Image转换为Format24bppRgb格式的BMP Bitmap bm = new Bitmap(image); BitmapData data = bm.LockBits(new Rectangle(0, 0, bm.Width, bm.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); try { //位图中第一个像素数据的地址。它也可以看成是位图中的第一个扫描行 IntPtr ptr = data.Scan0; //定义数组长度 int soureBitArrayLength = data.Height * Math.Abs(data.Stride); byte[] sourceBitArray = new byte[soureBitArrayLength]; //将bitmap中的内容拷贝到ptr_bgr数组中 MemoryHelper.Copy(ptr, sourceBitArray, 0, soureBitArrayLength); //填充引用对象字段值 imageInfo.width = data.Width; imageInfo.height = data.Height; imageInfo.format = ASF_ImagePixelFormat.ASVL_PAF_RGB24_B8G8R8; //获取去除对齐位后度图像数据 int line = imageInfo.width * 3; int pitch = Math.Abs(data.Stride); int bgr_len = line * imageInfo.height; byte[] destBitArray = new byte[bgr_len]; /* * 图片像素数据在内存中是按行存储,一般图像库都会有一个内存对齐,在每行像素的末尾位置 * 每行的对齐位会使每行多出一个像素空间(三通道如RGB会多出3个字节,四通道RGBA会多出4个字节) * 以下循环目的是去除每行末尾的对齐位,将有效的像素拷贝到新的数组 */ for (int i = 0; i < imageInfo.height; ++i) { Array.Copy(sourceBitArray, i * pitch, destBitArray, i * line, line); } imageInfo.imgData = MemoryHelper.Malloc(destBitArray.Length); MemoryHelper.Copy(destBitArray, 0, imageInfo.imgData, destBitArray.Length); return(imageInfo); } catch (Exception e) { //Console.WriteLine(e.Message); SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.ImageHelper), e.ToString()); } finally { bm.UnlockBits(data); } return(null); }
/// <summary> /// 用矩形框标记图片指定区域,添加年龄和性别标注 /// </summary> /// <param name="image">图片</param> /// <param name="startX">矩形框左上角X坐标</param> /// <param name="startY">矩形框左上角Y坐标</param> /// <param name="width">矩形框宽度</param> /// <param name="height">矩形框高度</param> /// <param name="age">年龄</param> /// <param name="gender">性别</param> /// <returns>标记后的图片</returns> public static Image MarkRectAndString(Image image, int startX, int startY, int width, int height, int age, int gender, int showWidth) { Image clone = (Image)image.Clone(); Graphics g = Graphics.FromImage(clone); try { Brush brush = new SolidBrush(Color.DeepPink); int penWidth = image.Width / showWidth; Pen pen = new Pen(brush, penWidth > 1 ? 2 * penWidth : 2); pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid; g.DrawRectangle(pen, new Rectangle(startX < 1 ? 0 : startX, startY < 1 ? 0 : startY, width, height)); string genderStr = ""; if (gender >= 0) { if (gender == 0) { genderStr = "男"; } else if (gender == 1) { genderStr = "女"; } } int fontSize = image.Width / showWidth; if (fontSize > 1) { int temp = 12; for (int i = 0; i < fontSize; i++) { temp += 6; } fontSize = temp; } else if (fontSize == 1) { fontSize = 14; } else { fontSize = 12; } g.DrawString($"年龄:约{age}岁 性别:{genderStr}", new Font(FontFamily.GenericSerif, fontSize), brush, startX < 1 ? 0 : startX, (startY - 20) < 1 ? 0 : startY - 20); return(clone); } catch (Exception e) { SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.ImageHelper), e.ToString()); } finally { g.Dispose(); } return(null); }
/// <summary> /// 提取单人脸特征 /// </summary> /// <param name="pEngine">人脸识别引擎</param> /// <param name="image">图片</param> /// <param name="singleFaceInfo">单人脸信息</param> /// <returns>单人脸特征</returns> public static IntPtr ExtractFeature(IntPtr pEngine, Image image, ASF_SingleFaceInfo singleFaceInfo) { ImageInfo imageInfo = ImageHelper.ReadBMP(image); IntPtr pSingleFaceInfo = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_SingleFaceInfo>()); MemoryHelper.StructureToPtr(singleFaceInfo, pSingleFaceInfo); IntPtr pFaceFeature = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_FaceFeature>()); int retCode = -1; try { retCode = ASFWrapper.ASFFaceFeatureExtract(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pSingleFaceInfo, pFaceFeature); } catch (Exception e) { //Console.WriteLine(e.Message); SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.FaceProcessHelper), $"Extract Feature Exception => {e.ToString()}"); } //Console.WriteLine("FR Extract Feature result:" + retCode); SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.FaceProcessHelper), $"FR Extract Feature result:{retCode} =>[{retCode.ToEnum<MError>().GetFieldDescription()}]"); if (retCode != 0) { //释放指针 MemoryHelper.Free(pSingleFaceInfo); MemoryHelper.Free(pFaceFeature); ASF_FaceFeature emptyFeature = new ASF_FaceFeature(); IntPtr pEmptyFeature = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_FaceFeature>()); MemoryHelper.StructureToPtr(emptyFeature, pEmptyFeature); return(pEmptyFeature); } //人脸特征feature过滤 ASF_FaceFeature faceFeature = MemoryHelper.PtrToStructure <ASF_FaceFeature>(pFaceFeature); byte[] feature = new byte[faceFeature.featureSize]; MemoryHelper.Copy(faceFeature.feature, feature, 0, faceFeature.featureSize); ASF_FaceFeature localFeature = new ASF_FaceFeature(); localFeature.feature = MemoryHelper.Malloc(feature.Length); MemoryHelper.Copy(feature, 0, localFeature.feature, feature.Length); localFeature.featureSize = feature.Length; IntPtr pLocalFeature = MemoryHelper.Malloc(MemoryHelper.SizeOf <ASF_FaceFeature>()); MemoryHelper.StructureToPtr(localFeature, pLocalFeature); //释放指针 MemoryHelper.Free(pSingleFaceInfo); MemoryHelper.Free(pFaceFeature); MemoryHelper.Free(imageInfo.imgData); return(pLocalFeature); }
/// <summary> /// 剪裁图片 /// </summary> /// <param name="src">原图片</param> /// <param name="left">左坐标</param> /// <param name="top">顶部坐标</param> /// <param name="right">右坐标</param> /// <param name="bottom">底部坐标</param> /// <returns>剪裁后的图片</returns> public static Image CutImage(Image src, int left, int top, int right, int bottom) { try { Bitmap srcBitmap = new Bitmap(src); Bitmap dstBitmap = srcBitmap.Clone(new Rectangle(left, top, right - left, bottom - top), PixelFormat.DontCare); return(dstBitmap); } catch (Exception e) { SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.ImageHelper), e.ToString()); } return(null); }
/// <summary> /// 按指定宽高缩放图片 /// </summary> /// <param name="image">原图片</param> /// <param name="dstWidth">目标图片宽</param> /// <param name="dstHeight">目标图片高</param> /// <returns></returns> public static Image ScaleImage(Image image, int dstWidth, int dstHeight) { Graphics g = null; try { //按比例缩放 float scaleRate = GetWidthAndHeight(image.Width, image.Height, dstWidth, dstHeight); int width = (int)(image.Width * scaleRate); int height = (int)(image.Height * scaleRate); //将宽度调整为4的整数倍 if (width % 4 != 0) { width = width - width % 4; } Bitmap destBitmap = new Bitmap(width, height); g = Graphics.FromImage(destBitmap); g.Clear(Color.Transparent); //设置画布的描绘质量 g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.DrawImage(image, new Rectangle((width - width) / 2, (height - height) / 2, width, height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); //设置压缩质量 EncoderParameters encoderParams = new EncoderParameters(); long[] quality = new long[1]; quality[0] = 100; EncoderParameter encoderParam = new EncoderParameter(Encoder.Quality, quality); encoderParams.Param[0] = encoderParam; return(destBitmap); } catch (Exception e) { SimplifiedLogHelper.WriteIntoSystemLog(nameof(Afw.Core.Helper.ImageHelper), e.ToString()); } finally { if (g != null) { g.Dispose(); } } return(null); }