/// <summary>
        /// 人脸3D角度检测
        /// </summary>
        /// <param name="pEngine">引擎Handle</param>
        /// <param name="imageInfo">图像数据</param>
        /// <param name="multiFaceInfo">人脸检测结果</param>
        /// <returns>保存人脸3D角度检测结果结构体</returns>
        public static ASF_Face3DAngle DetectFace3DAngle(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo, out int retCode)
        {
            IntPtr pMultiFaceInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_MultiFaceInfo>());

            UtilToolMemory.StructureToPtr(multiFaceInfo, pMultiFaceInfo);

            if (multiFaceInfo.faceNum == 0)
            {
                retCode = -1;
                return(new ASF_Face3DAngle());
            }

            //人脸信息处理
            retCode = ASFFunctions.ASFProcess(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, FaceEngineMask.ASF_FACE3DANGLE);
            if (retCode == 0)
            {
                //获取人脸3D角度
                IntPtr pFace3DAngleInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_Face3DAngle>());
                retCode = ASFFunctions.ASFGetFace3DAngle(pEngine, pFace3DAngleInfo);
                Console.WriteLine("Get Face3D Angle Result:" + retCode);
                ASF_Face3DAngle face3DAngle = UtilToolMemory.PtrToStructure <ASF_Face3DAngle>(pFace3DAngleInfo);

                //释放内存
                UtilToolMemory.Free(pMultiFaceInfo);
                UtilToolMemory.Free(pFace3DAngleInfo);

                return(face3DAngle);
            }
            else
            {
                return(new ASF_Face3DAngle());
            }
        }
        /// <summary>
        /// 性别检测
        /// </summary>
        /// <param name="pEngine">引擎Handle</param>
        /// <param name="imageInfo">图像数据</param>
        /// <param name="multiFaceInfo">人脸检测结果</param>
        /// <returns>保存性别检测结果结构体</returns>
        public static ASF_GenderInfo DetectGender(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo, out int retCode)
        {
            retCode = -1;
            IntPtr pMultiFaceInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_MultiFaceInfo>());

            UtilToolMemory.StructureToPtr(multiFaceInfo, pMultiFaceInfo);

            if (multiFaceInfo.faceNum == 0)
            {
                return(new ASF_GenderInfo());
            }

            //人脸信息处理
            retCode = ASFFunctions.ASFProcess(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, FaceEngineMask.ASF_GENDER);
            if (retCode == 0)
            {
                //获取性别信息
                IntPtr pGenderInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_GenderInfo>());
                retCode = ASFFunctions.ASFGetGender(pEngine, pGenderInfo);
                Console.WriteLine("Get Gender Result:" + retCode);
                ASF_GenderInfo genderInfo = UtilToolMemory.PtrToStructure <ASF_GenderInfo>(pGenderInfo);

                //释放内存
                UtilToolMemory.Free(pMultiFaceInfo);
                UtilToolMemory.Free(pGenderInfo);

                return(genderInfo);
            }
            else
            {
                return(new ASF_GenderInfo());
            }
        }
 public static ASF_MultiFaceInfo DetectFace(IntPtr pEngine, Image image)
 {
     lock (locks)
     {
         ASF_MultiFaceInfo multiFaceInfo = new ASF_MultiFaceInfo();
         if (image != null)
         {
             if (image == null)
             {
                 return(multiFaceInfo);
             }
             ImageInfo imageInfo = UtilTool.ReadImage(image);
             if (imageInfo == null)
             {
                 return(multiFaceInfo);
             }
             multiFaceInfo = DetectFace(pEngine, imageInfo);
             UtilToolMemory.Free(imageInfo.imgData);
             return(multiFaceInfo);
         }
         else
         {
             return(multiFaceInfo);
         }
     }
 }
        /// <summary>
        /// 年龄检测
        /// </summary>
        /// <param name="pEngine">引擎Handle</param>
        /// <param name="imageInfo">图像数据</param>
        /// <param name="multiFaceInfo">人脸检测结果</param>
        /// <returns>年龄检测结构体</returns>
        public static ASF_AgeInfo DetectAge(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo)
        {
            IntPtr pMultiFaceInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_MultiFaceInfo>());

            UtilToolMemory.StructureToPtr(multiFaceInfo, pMultiFaceInfo);

            if (multiFaceInfo.faceNum == 0)
            {
                return(new ASF_AgeInfo());
            }

            //人脸信息处理
            int retCode = ASFFunctions.ASFProcess(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, FaceEngineMask.ASF_AGE);

            //获取年龄信息
            IntPtr pAgeInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_AgeInfo>());

            retCode = ASFFunctions.ASFGetAge(pEngine, pAgeInfo);
            Console.WriteLine("Get Age Result:" + retCode);
            ASF_AgeInfo ageInfo = UtilToolMemory.PtrToStructure <ASF_AgeInfo>(pAgeInfo);

            //释放内存
            UtilToolMemory.Free(pMultiFaceInfo);
            UtilToolMemory.Free(pAgeInfo);

            return(ageInfo);
        }
        /// <summary>
        /// 提取人脸特征
        /// </summary>
        /// <param name="pEngine">引擎Handle</param>
        /// <param name="imageInfo">图像数据</param>
        /// <param name="multiFaceInfo">人脸检测结果</param>
        /// <returns>保存人脸特征结构体指针</returns>
        public static IntPtr ExtractFaceFeature(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo, out ASF_SingleFaceInfo singleFaceInfo)
        {
            singleFaceInfo = new ASF_SingleFaceInfo();
            if (multiFaceInfo.faceRects == null)
            {
                ASF_FaceFeature emptyFeature  = new ASF_FaceFeature();
                IntPtr          pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());
                UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature);
                return(pEmptyFeature);
            }
            singleFaceInfo.faceRect   = UtilToolMemory.PtrToStructure <MRECT>(multiFaceInfo.faceRects);
            singleFaceInfo.faceOrient = UtilToolMemory.PtrToStructure <int>(multiFaceInfo.faceOrients);
            IntPtr pSingleFaceInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_SingleFaceInfo>());

            UtilToolMemory.StructureToPtr(singleFaceInfo, pSingleFaceInfo);

            IntPtr pFaceFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());
            int    retCode      = ASFFunctions.ASFFaceFeatureExtract(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pSingleFaceInfo, pFaceFeature);

            Console.WriteLine("FR Extract Feature result:" + retCode);

            if (retCode != 0)
            {
                //释放指针
                UtilToolMemory.Free(pSingleFaceInfo);
                UtilToolMemory.Free(pFaceFeature);
                ASF_FaceFeature emptyFeature  = new ASF_FaceFeature();
                IntPtr          pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());
                UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature);
                return(pEmptyFeature);
            }

            //人脸特征feature过滤
            ASF_FaceFeature faceFeature = UtilToolMemory.PtrToStructure <ASF_FaceFeature>(pFaceFeature);

            byte[] feature = new byte[faceFeature.featureSize];
            UtilToolMemory.Copy(faceFeature.feature, feature, 0, faceFeature.featureSize);

            ASF_FaceFeature localFeature = new ASF_FaceFeature();

            localFeature.feature = UtilToolMemory.Malloc(feature.Length);
            UtilToolMemory.Copy(feature, 0, localFeature.feature, feature.Length);
            localFeature.featureSize = feature.Length;
            IntPtr pLocalFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());

            UtilToolMemory.StructureToPtr(localFeature, pLocalFeature);

            //释放指针
            UtilToolMemory.Free(pSingleFaceInfo);
            UtilToolMemory.Free(pFaceFeature);

            return(pLocalFeature);
        }
        /// <summary>
        /// 人脸检测(PS:检测RGB图像的人脸时,必须保证图像的宽度能被4整除,否则会失败)
        /// </summary>
        /// <param name="pEngine">引擎Handle</param>
        /// <param name="imageInfo">图像数据</param>
        /// <returns>人脸检测结果</returns>
        public static ASF_MultiFaceInfo DetectFace(IntPtr pEngine, ImageInfo imageInfo)
        {
            ASF_MultiFaceInfo multiFaceInfo  = new ASF_MultiFaceInfo();
            IntPtr            pMultiFaceInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_MultiFaceInfo>());
            int retCode = ASFFunctions.ASFDetectFaces(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo);

            if (retCode != 0)
            {
                UtilToolMemory.Free(pMultiFaceInfo);
                return(multiFaceInfo);
            }
            multiFaceInfo = UtilToolMemory.PtrToStructure <ASF_MultiFaceInfo>(pMultiFaceInfo);
            UtilToolMemory.Free(pMultiFaceInfo);
            return(multiFaceInfo);
        }
        /// <summary>
        /// 红外活体检测
        /// </summary>
        /// <param name="pEngine">引擎Handle</param>
        /// <param name="imageInfo">图像数据</param>
        /// <param name="multiFaceInfo">活体检测结果</param>
        /// <returns>保存活体检测结果结构体</returns>
        public static ASF_LivenessInfo LivenessInfo_IR(IntPtr pEngine, ImageInfo imageInfo, ASF_MultiFaceInfo multiFaceInfo, out int retCode)
        {
            IntPtr pMultiFaceInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_MultiFaceInfo>());

            UtilToolMemory.StructureToPtr(multiFaceInfo, pMultiFaceInfo);

            if (multiFaceInfo.faceNum == 0)
            {
                retCode = -1;
                //释放内存
                UtilToolMemory.Free(pMultiFaceInfo);
                return(new ASF_LivenessInfo());
            }

            try
            {
                //人脸信息处理
                retCode = ASFFunctions.ASFProcess_IR(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pMultiFaceInfo, FaceEngineMask.ASF_IR_LIVENESS);
                if (retCode == 0)
                {
                    //获取活体检测结果
                    IntPtr pLivenessInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_LivenessInfo>());
                    retCode = ASFFunctions.ASFGetLivenessScore_IR(pEngine, pLivenessInfo);
                    Console.WriteLine("Get Liveness Result:" + retCode);
                    ASF_LivenessInfo livenessInfo = UtilToolMemory.PtrToStructure <ASF_LivenessInfo>(pLivenessInfo);

                    //释放内存
                    UtilToolMemory.Free(pMultiFaceInfo);
                    UtilToolMemory.Free(pLivenessInfo);
                    return(livenessInfo);
                }
                else
                {
                    //释放内存
                    UtilToolMemory.Free(pMultiFaceInfo);
                    return(new ASF_LivenessInfo());
                }
            }
            catch
            {
                retCode = -1;
                //释放内存
                UtilToolMemory.Free(pMultiFaceInfo);
                return(new ASF_LivenessInfo());
            }
        }
        /// <summary>
        /// 单人脸性别检测
        /// </summary>
        /// <param name="pEngine">引擎Handle</param>
        /// <param name="image">图片</param>
        /// <param name="singleFaceInfo">单人脸信息</param>
        /// <returns>性别估计结果</returns>
        public static ASF_GenderInfo DetectGender(IntPtr pEngine, Image image, ASF_SingleFaceInfo singleFaceInfo)
        {
            ImageInfo imageInfo = UtilTool.ReadImage(image);

            if (imageInfo == null)
            {
                return(new ASF_GenderInfo());
            }
            ASF_MultiFaceInfo multiFaceInfo = new ASF_MultiFaceInfo();

            multiFaceInfo.faceRects = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <MRECT>());
            UtilToolMemory.StructureToPtr <MRECT>(singleFaceInfo.faceRect, multiFaceInfo.faceRects);
            multiFaceInfo.faceOrients = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <int>());
            UtilToolMemory.StructureToPtr <int>(singleFaceInfo.faceOrient, multiFaceInfo.faceOrients);
            multiFaceInfo.faceNum = 1;
            ASF_GenderInfo genderInfo = DetectGender(pEngine, imageInfo, multiFaceInfo);

            UtilToolMemory.Free(imageInfo.imgData);
            return(genderInfo);
        }
        /// <summary>
        /// 提取人脸特征
        /// </summary>
        /// <param name="pEngine">引擎Handle</param>
        /// <param name="image">图像</param>
        /// <returns>保存人脸特征结构体指针</returns>
        public static IntPtr ExtractFaceFeature(IntPtr pEngine, Image image, out ASF_SingleFaceInfo singleFaceInfo)
        {
            if (image.Width > 1536 || image.Height > 1536)
            {
                image = UtilTool.ScaleImage(image, 1536, 1536);
            }
            else
            {
                image = UtilTool.ScaleImage(image, image.Width, image.Height);
            }
            if (image == null)
            {
                singleFaceInfo = new ASF_SingleFaceInfo();
                ASF_FaceFeature emptyFeature  = new ASF_FaceFeature();
                IntPtr          pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());
                UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature);
                return(pEmptyFeature);
            }
            ImageInfo imageInfo = UtilTool.ReadImage(image);

            if (imageInfo == null)
            {
                singleFaceInfo = new ASF_SingleFaceInfo();
                ASF_FaceFeature emptyFeature  = new ASF_FaceFeature();
                IntPtr          pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());
                UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature);
                return(pEmptyFeature);
            }
            ASF_MultiFaceInfo multiFaceInfo = DetectFace(pEngine, imageInfo);

            singleFaceInfo = new ASF_SingleFaceInfo();
            IntPtr pFaceModel = ExtractFaceFeature(pEngine, imageInfo, multiFaceInfo, out singleFaceInfo);

            UtilToolMemory.Free(imageInfo.imgData);
            return(pFaceModel);
        }
        /// <summary>
        /// 提取单人脸特征
        /// </summary>
        /// <param name="pEngine">人脸识别引擎</param>
        /// <param name="image">图片</param>
        /// <param name="singleFaceInfo">单人脸信息</param>
        /// <returns>单人脸特征</returns>
        public static IntPtr ExtractFaceFeature(IntPtr pEngine, Image image, ASF_SingleFaceInfo singleFaceInfo)
        {
            ImageInfo imageInfo = UtilTool.ReadImage(image);

            if (imageInfo == null)
            {
                ASF_FaceFeature emptyFeature  = new ASF_FaceFeature();
                IntPtr          pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());
                UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature);
                return(pEmptyFeature);
            }
            IntPtr pSingleFaceInfo = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_SingleFaceInfo>());

            UtilToolMemory.StructureToPtr(singleFaceInfo, pSingleFaceInfo);

            IntPtr pFaceFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());
            int    retCode      = -1;

            try
            {
                retCode = ASFFunctions.ASFFaceFeatureExtract(pEngine, imageInfo.width, imageInfo.height, imageInfo.format, imageInfo.imgData, pSingleFaceInfo, pFaceFeature);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            Console.WriteLine("FR Extract Feature result:" + retCode);

            if (retCode != 0)
            {
                //释放指针
                UtilToolMemory.Free(pSingleFaceInfo);
                UtilToolMemory.Free(pFaceFeature);
                UtilToolMemory.Free(imageInfo.imgData);

                ASF_FaceFeature emptyFeature  = new ASF_FaceFeature();
                IntPtr          pEmptyFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());
                UtilToolMemory.StructureToPtr(emptyFeature, pEmptyFeature);
                return(pEmptyFeature);
            }

            //人脸特征feature过滤
            ASF_FaceFeature faceFeature = UtilToolMemory.PtrToStructure <ASF_FaceFeature>(pFaceFeature);

            byte[] feature = new byte[faceFeature.featureSize];
            UtilToolMemory.Copy(faceFeature.feature, feature, 0, faceFeature.featureSize);

            ASF_FaceFeature localFeature = new ASF_FaceFeature();

            localFeature.feature = UtilToolMemory.Malloc(feature.Length);
            UtilToolMemory.Copy(feature, 0, localFeature.feature, feature.Length);
            localFeature.featureSize = feature.Length;
            IntPtr pLocalFeature = UtilToolMemory.Malloc(UtilToolMemory.SizeOf <ASF_FaceFeature>());

            UtilToolMemory.StructureToPtr(localFeature, pLocalFeature);

            //释放指针
            UtilToolMemory.Free(pSingleFaceInfo);
            UtilToolMemory.Free(pFaceFeature);
            UtilToolMemory.Free(imageInfo.imgData);

            return(pLocalFeature);
        }
        /// <summary>
        /// RGB摄像头Paint事件,同步RGB人脸框,对比人脸框后进行IR活体检测
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void IrVideoSource_Paint(object sender, PaintEventArgs e)
        {
            if (isDoubleShot && FRC.MainView._irVideoSource.IsRunning)
            {
                //如果双摄,且IR摄像头工作,获取IR摄像头图片
                Bitmap irBitmap = FRC.MainView._irVideoSource.GetCurrentVideoFrame();
                if (irBitmap == null)
                {
                    return;
                }
                //得到Rect
                MRECT rect = new MRECT();
                lock (rectLock)
                {
                    rect = allRect;
                }
                float irOffsetX = FRC.MainView._irVideoSource.Width * 1f / irBitmap.Width;
                float irOffsetY = FRC.MainView._irVideoSource.Height * 1f / irBitmap.Height;
                float offsetX   = FRC.MainView._irVideoSource.Width * 1f / FRC.MainView._rgbVideoSource.Width;
                float offsetY   = FRC.MainView._irVideoSource.Height * 1f / FRC.MainView._rgbVideoSource.Height;
                //检测IR摄像头下最大人脸
                Graphics g = e.Graphics;

                float x      = rect.left * offsetX;
                float width  = rect.right * offsetX - x;
                float y      = rect.top * offsetY;
                float height = rect.bottom * offsetY - y;
                //根据Rect进行画框
                g.DrawRectangle(Pens.Red, x, y, width, height);
                if (trackIRUnit.message != "" && x > 0 && y > 0)
                {
                    //将上一帧检测结果显示到页面上
                    g.DrawString(trackIRUnit.message, font, trackIRUnit.message.Contains("活体") ? blueBrush : yellowBrush, x, y - 15);
                }

                //保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况
                if (isIRLock == false)
                {
                    isIRLock = true;
                    //异步处理提取特征值和比对,不然页面会比较卡
                    ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
                    {
                        if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0)
                        {
                            bool isLiveness = false;
                            try
                            {
                                //得到当前摄像头下的图片
                                if (irBitmap != null)
                                {
                                    //检测人脸,得到Rect框
                                    ASF_MultiFaceInfo irMultiFaceInfo = UtilToolFace.DetectFace(pVideoIRImageEngine, irBitmap);
                                    if (irMultiFaceInfo.faceNum <= 0)
                                    {
                                        return;
                                    }
                                    //得到最大人脸
                                    ASF_SingleFaceInfo irMaxFace = UtilToolFace.GetMaxFace(irMultiFaceInfo);
                                    //得到Rect
                                    MRECT irRect = irMaxFace.faceRect;
                                    //判断RGB图片检测的人脸框与IR摄像头检测的人脸框偏移量是否在误差允许范围内
                                    if (JudgeInAllowErrorRange(rect.left * offsetX / irOffsetX, irRect.left) && JudgeInAllowErrorRange(rect.right * offsetX / irOffsetX, irRect.right) &&
                                        JudgeInAllowErrorRange(rect.top * offsetY / irOffsetY, irRect.top) && JudgeInAllowErrorRange(rect.bottom * offsetY / irOffsetY, irRect.bottom))
                                    {
                                        int retCode_Liveness = -1;
                                        //将图片进行灰度转换,然后获取图片数据
                                        ImageInfo irImageInfo = UtilTool.ReadBMP_IR(irBitmap);
                                        if (irImageInfo == null)
                                        {
                                            return;
                                        }
                                        //IR活体检测
                                        ASF_LivenessInfo liveInfo = UtilToolFace.LivenessInfo_IR(pVideoIRImageEngine, irImageInfo, irMultiFaceInfo, out retCode_Liveness);
                                        //判断检测结果
                                        if (retCode_Liveness == 0 && liveInfo.num > 0)
                                        {
                                            int isLive = UtilToolMemory.PtrToStructure <int>(liveInfo.isLive);
                                            isLiveness = (isLive == 1) ? true : false;
                                        }
                                        if (irImageInfo != null)
                                        {
                                            UtilToolMemory.Free(irImageInfo.imgData);
                                        }
                                    }
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);
                            }
                            finally
                            {
                                trackIRUnit.message = string.Format("IR{0}", isLiveness ? "活体" : "假体");
                                if (irBitmap != null)
                                {
                                    irBitmap.Dispose();
                                }
                                isIRLock = false;
                            }
                        }
                        else
                        {
                            trackIRUnit.message = string.Empty;
                        }
                        isIRLock = false;
                    }));
                }
            }
        }
        /// <summary>
        /// RGB摄像头Paint事件,图像显示到窗体上,得到每一帧图像,并进行处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public void VideoSource_Paint(object sender, PaintEventArgs e)
        {
            if (FRC.MainView._rgbVideoSource.IsRunning)
            {
                //得到当前RGB摄像头下的图片
                Bitmap bitmap = FRC.MainView._rgbVideoSource.GetCurrentVideoFrame();
                if (bitmap == null)
                {
                    return;
                }
                //检测人脸,得到Rect框
                ASF_MultiFaceInfo multiFaceInfo = UtilToolFace.DetectFace(pVideoEngine, bitmap);
                //得到最大人脸
                ASF_SingleFaceInfo maxFace = UtilToolFace.GetMaxFace(multiFaceInfo);
                //得到Rect
                MRECT rect = maxFace.faceRect;
                //检测RGB摄像头下最大人脸
                Graphics g       = e.Graphics;
                float    offsetX = FRC.MainView._rgbVideoSource.Width * 1f / bitmap.Width;
                float    offsetY = FRC.MainView._rgbVideoSource.Height * 1f / bitmap.Height;
                float    x       = rect.left * offsetX;
                float    width   = rect.right * offsetX - x;
                float    y       = rect.top * offsetY;
                float    height  = rect.bottom * offsetY - y;
                //根据Rect进行画框
                g.DrawRectangle(Pens.Red, x, y, width, height);
                if (trackRGBUnit.message != "" && x > 0 && y > 0)
                {
                    //将上一帧检测结果显示到页面上
                    g.DrawString(trackRGBUnit.message, font, trackRGBUnit.message.Contains("活体") ? blueBrush : yellowBrush, x, y - 15);
                }

                //保证只检测一帧,防止页面卡顿以及出现其他内存被占用情况
                if (isRGBLock == false)
                {
                    isRGBLock = true;
                    //异步处理提取特征值和比对,不然页面会比较卡
                    ThreadPool.QueueUserWorkItem(new WaitCallback(delegate
                    {
                        if (rect.left != 0 && rect.right != 0 && rect.top != 0 && rect.bottom != 0)
                        {
                            try
                            {
                                lock (rectLock)
                                {
                                    allRect.left   = (int)(rect.left * offsetX);
                                    allRect.top    = (int)(rect.top * offsetY);
                                    allRect.right  = (int)(rect.right * offsetX);
                                    allRect.bottom = (int)(rect.bottom * offsetY);
                                }

                                bool isLiveness = false;

                                //调整图片数据,非常重要
                                ImageInfo imageInfo = UtilTool.ReadImage(bitmap);
                                if (imageInfo == null)
                                {
                                    return;
                                }
                                int retCode_Liveness = -1;
                                //RGB活体检测
                                ASF_LivenessInfo liveInfo = UtilToolFace.LivenessInfo_RGB(pVideoRGBImageEngine, imageInfo, multiFaceInfo, out retCode_Liveness);
                                //判断检测结果
                                if (retCode_Liveness == 0 && liveInfo.num > 0)
                                {
                                    int isLive = UtilToolMemory.PtrToStructure <int>(liveInfo.isLive);
                                    isLiveness = (isLive == 1) ? true : false;
                                }
                                if (imageInfo != null)
                                {
                                    UtilToolMemory.Free(imageInfo.imgData);
                                }
                                if (isLiveness)
                                {
                                    //提取人脸特征
                                    IntPtr feature   = UtilToolFace.ExtractFaceFeature(pVideoRGBImageEngine, bitmap, maxFace);
                                    float similarity = 0f;
                                    //得到比对结果
                                    int result = CompareFeature(feature, out similarity);
                                    UtilToolMemory.Free(feature);
                                    if (result > -1)
                                    {
                                        //将比对结果放到显示消息中,用于最新显示
                                        trackRGBUnit.message = string.Format(" {0}号 {1},{2}", result, similarity, string.Format("RGB{0}", isLiveness ? "活体" : "假体"));
                                    }
                                    else
                                    {
                                        //显示消息
                                        trackRGBUnit.message = string.Format("RGB{0}", isLiveness ? "活体" : "假体");
                                    }
                                }
                                else
                                {
                                    //显示消息
                                    trackRGBUnit.message = string.Format("RGB{0}", isLiveness ? "活体" : "假体");
                                }
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);
                            }
                            finally
                            {
                                if (bitmap != null)
                                {
                                    bitmap.Dispose();
                                }
                                isRGBLock = false;
                            }
                        }
                        else
                        {
                            lock (rectLock)
                            {
                                allRect.left   = 0;
                                allRect.top    = 0;
                                allRect.right  = 0;
                                allRect.bottom = 0;
                            }
                        }
                        isRGBLock = false;
                    }));
                }
            }
        }
示例#13
0
        /// <summary>
        /// “选择图片识别”
        /// </summary>
        public void ChooseImgeDistinguish(bool IsOffline)
        {
            //判断引擎是否初始化成功
            if (pImageEngine == IntPtr.Zero)
            {
                //禁用相关功能按钮
                FRC.MainVM.IsSIIBtnEnable = false;
                FRC.MainVM.IsPGIBtnEnable = false;
                //ControlsEnable(false, chooseMultiImgBtn, matchBtn, btnClearFaceList, chooseImgBtn);
                MessageBox.Show("请先初始化引擎!");
                return;
            }

            List <string> imagePathList = ImportImages(IsOffline, false);//单张照片

            if (imagePathList.Count <= 0)
            {
                return;
            }
            string selectedImagePath = imagePathList[0];

            DateTime detectStartTime = DateTime.Now;

            AppendText(string.Format("------------------------------开始检测,时间:{0}------------------------------\n", detectStartTime.ToString("yyyy-MM-dd HH:mm:ss:ms")));

            //获取文件,拒绝过大的图片
            FileInfo fileInfo = new FileInfo(selectedImagePath);

            if (fileInfo.Length > MaxSize)
            {
                MessageBox.Show("图像文件最大为2MB,请压缩后再导入!");
                AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")));
                AppendText("\n");
                return;
            }

            Image srcImage = UtilTool.ReadImageFromFile(selectedImagePath);

            if (srcImage == null)
            {
                MessageBox.Show("图像数据获取失败,请稍后重试!");
                AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")));
                AppendText("\n");
                return;
            }
            if (srcImage.Width > 1536 || srcImage.Height > 1536)
            {
                srcImage = UtilTool.ScaleImage(srcImage, 1536, 1536);
            }
            if (srcImage == null)
            {
                MessageBox.Show("图像数据获取失败,请稍后重试!");
                AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")));
                AppendText("\n");
                return;
            }
            //调整图像宽度,需要宽度为4的倍数
            if (srcImage.Width % 4 != 0)
            {
                srcImage = UtilTool.ScaleImage(srcImage, srcImage.Width - (srcImage.Width % 4), srcImage.Height);
            }
            //调整图片数据,非常重要
            ImageInfo imageInfo = UtilTool.ReadImage(srcImage);

            if (imageInfo == null)
            {
                MessageBox.Show("图像数据获取失败,请稍后重试!");
                AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")));
                AppendText("\n");
                return;
            }
            //人脸检测
            ASF_MultiFaceInfo multiFaceInfo = UtilToolFace.DetectFace(pImageEngine, imageInfo);
            //年龄检测
            int         retCode_Age = -1;
            ASF_AgeInfo ageInfo     = UtilToolFace.DetectAge(pImageEngine, imageInfo, multiFaceInfo, out retCode_Age);
            //性别检测
            int            retCode_Gender = -1;
            ASF_GenderInfo genderInfo     = UtilToolFace.DetectGender(pImageEngine, imageInfo, multiFaceInfo, out retCode_Gender);

            //3DAngle检测
            int             retCode_3DAngle = -1;
            ASF_Face3DAngle face3DAngleInfo = UtilToolFace.DetectFace3DAngle(pImageEngine, imageInfo, multiFaceInfo, out retCode_3DAngle);

            UtilToolMemory.Free(imageInfo.imgData);

            if (multiFaceInfo.faceNum < 1)
            {
                srcImage     = UtilTool.ScaleImage(srcImage, (int)FRC.FIView._faceIdentificationImageBox.Width, (int)FRC.FIView._faceIdentificationImageBox.Height);
                ImageFeature = IntPtr.Zero;
                FRC.FIView._faceIdentificationImageBox.Source = UtilTool.BitmapToBitmapImage(srcImage);
                AppendText(string.Format("{0} - 未检测出人脸!\n\n", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss")));
                AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:ms")));
                AppendText("\n");
                return;
            }

            MRECT temp       = new MRECT();
            int   ageTemp    = 0;
            int   genderTemp = 0;
            int   rectTemp   = 0;

            //标记出检测到的人脸
            for (int i = 0; i < multiFaceInfo.faceNum; i++)
            {
                MRECT rect   = UtilToolMemory.PtrToStructure <MRECT>(multiFaceInfo.faceRects + UtilToolMemory.SizeOf <MRECT>() * i);
                int   orient = UtilToolMemory.PtrToStructure <int>(multiFaceInfo.faceOrients + UtilToolMemory.SizeOf <int>() * i);
                int   age    = 0;

                if (retCode_Age != 0)
                {
                    AppendText(string.Format("年龄检测失败,返回{0}!\n\n", retCode_Age));
                }
                else
                {
                    age = UtilToolMemory.PtrToStructure <int>(ageInfo.ageArray + UtilToolMemory.SizeOf <int>() * i);
                }

                int gender = -1;
                if (retCode_Gender != 0)
                {
                    AppendText(string.Format("性别检测失败,返回{0}!\n\n", retCode_Gender));
                }
                else
                {
                    gender = UtilToolMemory.PtrToStructure <int>(genderInfo.genderArray + UtilToolMemory.SizeOf <int>() * i);
                }

                int   face3DStatus = -1;
                float roll         = 0f;
                float pitch        = 0f;
                float yaw          = 0f;
                if (retCode_3DAngle != 0)
                {
                    AppendText(string.Format("3DAngle检测失败,返回{0}!\n\n", retCode_3DAngle));
                }
                else
                {
                    //角度状态 非0表示人脸不可信
                    face3DStatus = UtilToolMemory.PtrToStructure <int>(face3DAngleInfo.status + UtilToolMemory.SizeOf <int>() * i);
                    //roll为侧倾角,pitch为俯仰角,yaw为偏航角
                    roll  = UtilToolMemory.PtrToStructure <float>(face3DAngleInfo.roll + UtilToolMemory.SizeOf <float>() * i);
                    pitch = UtilToolMemory.PtrToStructure <float>(face3DAngleInfo.pitch + UtilToolMemory.SizeOf <float>() * i);
                    yaw   = UtilToolMemory.PtrToStructure <float>(face3DAngleInfo.yaw + UtilToolMemory.SizeOf <float>() * i);
                }

                int rectWidth  = rect.right - rect.left;
                int rectHeight = rect.bottom - rect.top;

                //查找最大人脸
                if (rectWidth * rectHeight > rectTemp)
                {
                    rectTemp   = rectWidth * rectHeight;
                    temp       = rect;
                    ageTemp    = age;
                    genderTemp = gender;
                }
                AppendText(string.Format("{0} - 人脸坐标:[left:{1},top:{2},right:{3},bottom:{4},orient:{5},roll:{6},pitch:{7},yaw:{8},status:{11}] Age:{9} Gender:{10}\n", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), rect.left, rect.top, rect.right, rect.bottom, orient, roll, pitch, yaw, age, (gender >= 0 ? gender.ToString() : ""), face3DStatus));
            }

            AppendText(string.Format("{0} - 人脸数量:{1}\n\n", DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), multiFaceInfo.faceNum));

            DateTime detectEndTime = DateTime.Now;

            AppendText(string.Format("------------------------------检测结束,时间:{0}------------------------------\n", detectEndTime.ToString("yyyy-MM-dd HH:mm:ss:ms")));
            AppendText("\n");
            ASF_SingleFaceInfo singleFaceInfo = new ASF_SingleFaceInfo();

            //提取人脸特征
            ImageFeature = UtilToolFace.ExtractFaceFeature(pImageEngine, srcImage, out singleFaceInfo);

            //清空上次的匹配结果
            for (int i = 0; i < ImagesFeatureList.Count; i++)
            {
                //_imageList.Items[i].Text = string.Format("{0}号", i);
            }
            //获取缩放比例
            float scaleRate = UtilTool.GetWidthAndHeight(srcImage.Width, srcImage.Height, (int)FRC.FIView._faceIdentificationImageBox.Width, (int)FRC.FIView._faceIdentificationImageBox.Height);

            //缩放图片
            srcImage = UtilTool.ScaleImage(srcImage, (int)FRC.FIView._faceIdentificationImageBox.Width, (int)FRC.FIView._faceIdentificationImageBox.Height);
            //添加标记
            srcImage = UtilTool.MarkRectAndString(srcImage,
                                                  (int)(temp.left * scaleRate),
                                                  (int)(temp.top * scaleRate),
                                                  (int)(temp.right * scaleRate) - (int)(temp.left * scaleRate),
                                                  (int)(temp.bottom * scaleRate) - (int)(temp.top * scaleRate),
                                                  ageTemp, genderTemp,
                                                  (int)FRC.FIView._faceIdentificationImageBox.Width);

            //显示标记后的图像
            FRC.FIView._faceIdentificationImageBox.Source = UtilTool.BitmapToBitmapImage(srcImage);

            MatchImage();
        }