/// <summary>
        /// Returns an enumerable collection of dictionary of face parts locations (eyes, nose, etc) for each face in the image.
        /// </summary>
        /// <param name="faceImage">The image contains faces. The image can contain multiple faces.</param>
        /// <param name="faceLocations">The enumerable collection of location rectangle for faces. If specified null, method will find face locations.</param>
        /// <param name="model">The model of face detector.</param>
        /// <returns>An enumerable collection of dictionary of face parts locations (eyes, nose, etc).</returns>
        /// <exception cref="ArgumentNullException"><paramref name="faceImage"/> is null.</exception>
        /// <exception cref="ObjectDisposedException"><paramref name="faceImage"/> or this object is disposed.</exception>
        public IEnumerable <IDictionary <FacePart, IEnumerable <Point> > > FaceLandmark(Image faceImage, IEnumerable <Location> faceLocations = null, PredictorModel model = PredictorModel.Large)
        {
            if (faceImage == null)
            {
                throw new ArgumentNullException(nameof(faceImage));
            }
            if (faceImage.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(faceImage));
            }
            if (this.IsDisposed)
            {
                throw new ObjectDisposedException(nameof(FaceEncoding));
            }

            var landmarks      = this.RawFaceLandmarks(faceImage, faceLocations, model);
            var landmarkTuples = landmarks.Select(landmark => Enumerable.Range(0, (int)landmark.Parts)
                                                  .Select(index => new Point(landmark.GetPart((uint)index))).ToArray());

            // For a definition of each point index, see https://cdn-images-1.medium.com/max/1600/1*AbEg31EgkbXSQehuNJBlWg.png
            switch (model)
            {
            case PredictorModel.Large:
                foreach (var landmarkTuple in landmarkTuples)
                {
                    yield return new Dictionary <FacePart, IEnumerable <Point> >
                           {
                               { FacePart.Chin, Enumerable.Range(0, 17).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.LeftEyebrow, Enumerable.Range(17, 5).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.RightEyebrow, Enumerable.Range(22, 5).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.NoseBridge, Enumerable.Range(27, 5).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.NoseTip, Enumerable.Range(31, 5).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.LeftEye, Enumerable.Range(36, 6).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.RightEye, Enumerable.Range(42, 6).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.TopLip, Enumerable.Range(48, 7).Select(i => landmarkTuple[i])
                                 .Concat(new [] { landmarkTuple[64] })
                                 .Concat(new [] { landmarkTuple[63] })
                                 .Concat(new [] { landmarkTuple[62] })
                                 .Concat(new [] { landmarkTuple[61] })
                                 .Concat(new [] { landmarkTuple[60] }) },
                               { FacePart.BottomLip, Enumerable.Range(54, 6).Select(i => landmarkTuple[i])
                                 .Concat(new [] { landmarkTuple[48] })
                                 .Concat(new [] { landmarkTuple[60] })
                                 .Concat(new [] { landmarkTuple[67] })
                                 .Concat(new [] { landmarkTuple[66] })
                                 .Concat(new [] { landmarkTuple[65] })
                                 .Concat(new [] { landmarkTuple[64] }) }
                           }
                }
                ;
                break;

            case PredictorModel.Small:
                foreach (var landmarkTuple in landmarkTuples)
                {
                    yield return new Dictionary <FacePart, IEnumerable <Point> >
                           {
                               { FacePart.NoseTip, Enumerable.Range(4, 1).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.LeftEye, Enumerable.Range(2, 2).Select(i => landmarkTuple[i]).ToArray() },
                               { FacePart.RightEye, Enumerable.Range(0, 2).Select(i => landmarkTuple[i]).ToArray() }
                           }
                }
                ;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(model), model, null);
            }
        }
        private IEnumerable <FullObjectDetection> RawFaceLandmarks(Image img, IEnumerable <Location> faceLocations = null, PredictorModel model = PredictorModel.Large)
        {
            var method = this._FaceRecognition.GetType().GetMethod("RawFaceLandmarks", BindingFlags.Instance | BindingFlags.NonPublic);

            return(method.Invoke(this._FaceRecognition, new object[] { img, faceLocations, model }) as IEnumerable <FullObjectDetection>);
        }
Beispiel #3
0
        private IEnumerable <FullObjectDetection> RawFaceLandmarks(Image faceImage, IEnumerable <Location> faceLocations = null, PredictorModel model = PredictorModel.Large)
        {
            IEnumerable <MModRect> tmp;

            if (faceLocations == null)
            {
                tmp = this.RawFaceLocations(faceImage);
            }
            else
            {
                tmp = faceLocations.Select(l => new MModRect {
                    Rect = new Rectangle {
                        Bottom = l.Bottom, Left = l.Left, Top = l.Top, Right = l.Right
                    }
                });
            }

            var posePredictor = this._PosePredictor68Point;

            if (model == PredictorModel.Small)
            {
                posePredictor = this._PosePredictor5Point;
            }

            foreach (var rect in tmp)
            {
                yield return(posePredictor.Detect(faceImage.Matrix, rect));
            }
        }
        private void FaceLandmark(string testName, PredictorModel model)
        {
            const int pointSize = 2;

            var path = Path.Combine(ImageDirectory, TwoPersonFile);

            if (!File.Exists(path))
            {
                var binary = new HttpClient().GetByteArrayAsync($"{TwoPersonUrl}/{TwoPersonFile}").Result;

                Directory.CreateDirectory(ImageDirectory);
                File.WriteAllBytes(path, binary);
            }

            foreach (var mode in new[] { Mode.Rgb, Mode.Greyscale })
            {
                using (var image = FaceRecognition.LoadImageFile(path, mode))
                {
                    var landmarks = this._FaceRecognition.FaceLandmark(image, null, model).ToArray();
                    Assert.IsTrue(landmarks.Length > 1, $"{mode}");

                    foreach (var facePart in Enum.GetValues(typeof(FacePart)).Cast <FacePart>())
                    {
                        using (var bitmap = System.Drawing.Image.FromFile(path))
                        {
                            var draw = false;
                            using (var g = Graphics.FromImage(bitmap))
                                foreach (var landmark in landmarks)
                                {
                                    if (landmark.ContainsKey(facePart))
                                    {
                                        draw = true;
                                        foreach (var p in landmark[facePart].ToArray())
                                        {
                                            g.DrawEllipse(Pens.GreenYellow, p.X - pointSize, p.Y - pointSize, pointSize * 2, pointSize * 2);
                                        }
                                    }
                                }

                            if (draw)
                            {
                                var directory = Path.Combine(ResultDirectory, testName);
                                Directory.CreateDirectory(directory);

                                var dst = Path.Combine(directory, $"{facePart}-{mode}.bmp");
                                bitmap.Save(dst, ImageFormat.Bmp);
                            }
                        }
                    }

                    using (var bitmap = System.Drawing.Image.FromFile(path))
                    {
                        using (var g = Graphics.FromImage(bitmap))
                            foreach (var landmark in landmarks)
                            {
                                foreach (var points in landmark.Values)
                                {
                                    foreach (var p in points)
                                    {
                                        g.DrawEllipse(Pens.GreenYellow, p.X - pointSize, p.Y - pointSize, pointSize * 2, pointSize * 2);
                                    }
                                }
                            }

                        var directory = Path.Combine(ResultDirectory, testName);
                        Directory.CreateDirectory(directory);

                        var dst = Path.Combine(directory, $"All-{mode}.bmp");
                        bitmap.Save(dst, ImageFormat.Bmp);
                    }
                }
            }
        }