Monday, December 18, 2017

[C#] VGG Face CNN descriptor first try

VGG_Face0
It's time to try face detection since done lot of object detection. At this post, I will try VGG Face Descriptor, test the pre-trained model result, then see what we can do in next phase.

As usual, OpenCv Dnn is our model test good friend.

This test will be very simple and short, let see the code.
            var file = "jeremy-clarkson.jpg";
            //var file = "john-cena.jpg";
            var prototxt = "VGG_FACE_deploy.prototxt";
            var model = "VGG_FACE.caffemodel";
            var labeltxt = "names.txt";
Set variable.


            var org = Cv2.ImRead(file);
            var blob = CvDnn.BlobFromImage(org, 1, new Size(224, 224));
            var net = CvDnn.ReadNetFromCaffe(prototxt, model);
            net.SetInput(blob, "data");
            var prob = net.Forward("prob");
Load image, setup model, input image and forward it.


            var probList = new Dictionary();
            for (int i = 0; i < prob.Width; i++)
            {
                probList.Add(i,prob.At(0,i));
            }
Convert result from [1,2622] array to a dictionary with index for later use.

            var top3 = probList.OrderByDescending(x => x.Value).Take(3).ToList();
            foreach (var result in top3)
            {
                Console.WriteLine($"{labels[result.Key]}:{result.Value*100:0.00}%");
            }
            org.PutText($"{labels[top3.First().Key]}:{top3.First().Value * 100:0.00}%",
                new Point(0, 25), HersheyFonts.HersheyTriplex, 1, Scalar.OrangeRed);
Print out top 3 close result, and draw top 1 result to image.

Now we can put in some pictures to test it, I am a big fan of Top Gear,and The Grand Tour season 2 just start at Dec 8, so I choose using The Holy Trinity from the show to test.

VGG_Face01

Jeremy Clarkon : Correct Answer, but 61% confidence not high enough.


VGG_Face02

James May : Wrong Answer, sadly James May is not one of 2622 pre-trained faces, so we can't get the correct answer, but coincidentally the system thought he is Richard Hammond lol.


VGG_Face03

Richard Hammond : Correct Answer, with 100% confidence!!

Since James May didn't include in the pre-trained model, So I decide find one more people to test.



Oops.... this one....

VGG_Face04
John Cena : Correct Answer, with very high confidence.


Overall, OGG Face seems is a good model for detect face, next phase I will implement face crop feature, so we can detect multi face in one picture.

Here is the full code.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using OpenCvSharp;
using OpenCvSharp.Dnn;

namespace OpenCvDnnVggFace
{
    class Program
    {
        static void Main()
        {
            //model can get from http://www.robots.ox.ac.uk/~vgg/software/vgg_face/
            var file = "jeremy-clarkson.jpg";
            var prototxt = "VGG_FACE_deploy.prototxt";
            var model = "VGG_FACE.caffemodel";
            var labeltxt = "names.txt";

            //read all names
            var labels = ReadLabels(labeltxt);
            var org = Cv2.ImRead(file);
            var blob = CvDnn.BlobFromImage(org, 1, new Size(224, 224));
            var net = CvDnn.ReadNetFromCaffe(prototxt, model);
            net.SetInput(blob, "data");

            Stopwatch sw = new Stopwatch();
            sw.Start();
            //forward model
            var prob = net.Forward("prob");
            sw.Stop();
            Console.WriteLine($"Runtime:{sw.ElapsedMilliseconds} ms");

            //convert result to list
            var probList = new Dictionary();
            for (int i = 0; i < prob.Width; i++)
            {
                probList.Add(i,prob.At(0,i));
            }
            
            //get top 3
            var top3 = probList.OrderByDescending(x => x.Value).Take(3).ToList();
            foreach (var result in top3)
            {
                Console.WriteLine($"{labels[result.Key]}:{result.Value*100:0.00}%");
            }

            //draw result
            org.PutText($"{labels[top3.First().Key]}:{top3.First().Value * 100:0.00}%",
                new Point(0, 25), HersheyFonts.HersheyTriplex, 1, Scalar.OrangeRed);
            using (new Window("image", org))
            {
                Cv2.WaitKey();
            }
        }

        // Load label name list
        public static string[] ReadLabels(string file)
        {
            string patten = "(?.*)\n";
            var result = new List();
            using (FileStream stream = File.OpenRead(file))
            using (StreamReader reader = new StreamReader(stream))
            {
                string text = reader.ReadToEnd();
                if (string.IsNullOrWhiteSpace(text))
                {
                    return result.ToArray();
                }

                Regex regex = new Regex(patten);
                var matches = regex.Matches(text);
                foreach (Match match in matches)
                {
                    var name = match.Groups[1].Value;

                    result.Add(name);
                }
                return result.ToArray();
            }
        }
    }
}

Or you can get it from my github.

Hope you enjoy it.

No comments:

Post a Comment