private Task <RetrieveResult> FindFaceEyesIrisAsync()
        {
            return(Task <RetrieveResult> .Run(() =>
            {
                detector.DetectFace(grayFrame, out FaceRetrieveResult face, out EyeRetrieveResult eye);
                if (!face.HasFace)
                {
                    return null;
                }
                bool hasLeftPupil = false;
                CIRCLE leftPupil = default;
                if (eye.HasLeftEye)
                {
                    RECT leftEye = eye.LeftEye;
                    int offsety = (int)(leftEye.Height * 0.2);
                    int offsetx = (int)(leftEye.Width * 0.1);
                    leftEye.Offset(offsetx, offsety);
                    leftEye.Height = leftEye.Height - offsety - offsety;

                    leftPupil = Iris.SearchInnerBoundary(grayBytes, img_width, img_height, leftEye.Left, leftEye.Top, leftEye.Right, leftEye.Bottom);
                }
                bool hasRightPupil = false;
                CIRCLE rightPupil = default;
                if (eye.HasRightEye)
                {
                    RECT rightEye = eye.RightEye;
                    int offsety = (int)(rightEye.Height * 0.2);
                    int offsetx = (int)(rightEye.Width * 0.1);
                    rightEye.Offset(-offsetx, offsety);
                    rightEye.Height = rightEye.Height - offsety - offsety;
                    rightPupil = Iris.SearchInnerBoundary(grayBytes, img_width, img_height, rightEye.Left, rightEye.Top, rightEye.Right, rightEye.Bottom);
                }
                return new RetrieveResult()
                {
                    Face = face,
                    Eye = eye,
                    Pupil = new PupilRetrieveResult(hasLeftPupil, leftPupil, hasRightPupil, rightPupil),
                };
            }));
        }
        private void FindFaceFeatures()
        {
            Marshal.Copy(grayFrame.DataPointer, grayBytes, 0, img_size);
            FindFaceEyesIrisAsync().ContinueWith((tsk) =>
            {
                RetrieveResult retrieveResult = tsk.Result;
                if (retrieveResult == null)
                {
                    Dispatcher.BeginInvoke((Action)(() =>
                    {
                        BitmapSource grayImage = BitmapSource.Create(
                            img_width, img_height,
                            96.0, 96.0, PixelFormats.Gray8,
                            new BitmapPalette(new System.Windows.Media.Color[] { System.Windows.Media.Color.FromRgb(0, 0, 0), System.Windows.Media.Color.FromRgb(255, 255, 255) }),
                            grayBytes, img_width);
                        resultWindow.SetResult(grayImage, grayImage);
                        lock (_locker)
                        {
                            isReady = true;
                            if ((capture.Grab() == false))
                            {
                                App.Current.Shutdown();
                            }
                        }
                    }), DispatcherPriority.Render);
                    return;
                }

                FaceRetrieveResult faceRetrieveResult   = retrieveResult.Face;
                EyeRetrieveResult eyeRetrieveResult     = retrieveResult.Eye;
                PupilRetrieveResult pupilRetrieveResult = retrieveResult.Pupil;
                Emgu.CV.Structure.MCvScalar whiteColor  = new Emgu.CV.Structure.MCvScalar(100, 255, 255);
                Emgu.CV.Structure.MCvScalar redColor    = new Emgu.CV.Structure.MCvScalar(100, 255, 100);
                if (faceRetrieveResult.HasFace)
                {
                    RECT face = faceRetrieveResult.Face;
                    CvInvoke.Rectangle(cameraFrame, face, whiteColor, 3);
                    if (eyeRetrieveResult.HasLeftEye)
                    {
                        RECT leftEye     = eyeRetrieveResult.LeftEye;
                        CIRCLE leftPupil = pupilRetrieveResult.LeftPupil;
                        CvInvoke.Rectangle(cameraFrame, leftEye, whiteColor, 3);
                        CvInvoke.Circle(cameraFrame, leftPupil.Center, leftPupil.Radius, redColor, 2);
                    }
                    if (eyeRetrieveResult.HasRightEye)
                    {
                        RECT rightEye     = eyeRetrieveResult.RightEye;
                        CIRCLE rightPupil = pupilRetrieveResult.RightPupil;
                        CvInvoke.Rectangle(cameraFrame, rightEye, whiteColor, 3);
                        CvInvoke.Circle(cameraFrame, rightPupil.Center, rightPupil.Radius, redColor, 2);
                    }
                }

                Dispatcher.BeginInvoke((Action)(() =>
                {
                    OnFeatureRead(eyeRetrieveResult, pupilRetrieveResult);
                    BitmapSource grayImage = BitmapSource.Create(
                        img_width, img_height,
                        96.0, 96.0, PixelFormats.Gray8,
                        new BitmapPalette(new System.Windows.Media.Color[] { System.Windows.Media.Color.FromRgb(0, 0, 0), System.Windows.Media.Color.FromRgb(255, 255, 255) }),
                        grayBytes, img_width);
                    BitmapSource resultImage = Bitmap2BitmapImage(cameraFrame.Bitmap);
                    resultWindow.SetResult(grayImage, resultImage);

                    lock (_locker)
                    {
                        isReady = true;
                        if ((capture.Grab() == false))
                        {
                            App.Current.Shutdown();
                        }
                    }
                }), DispatcherPriority.Render);
            });
        }