private static void Load(string directory, out IList <Matrix <RgbPixel> > images, out IList <uint> labels) { var imageList = new List <Matrix <RgbPixel> >(); var labelList = new List <uint>(); foreach (var file in Directory.EnumerateFiles(directory)) { var name = Path.GetFileName(file); var s = name.Split('_'); if (s.Length != 4 || !uint.TryParse(s[1], out var gender)) { continue; } using (var tmp = Dlib.LoadImageAsMatrix <RgbPixel>(file)) { var m = new Matrix <RgbPixel>(Size, Size); Dlib.ResizeImage(tmp, m); imageList.Add(m); labelList.Add(gender); } } images = imageList; labels = labelList; }
private static void Preprocess(string type, string input, FrontalFaceDetector faceDetector, ShapePredictor posePredictor, string output) { var imageCount = 0; var r = new ulong[Size * Size]; var g = new ulong[Size * Size]; var b = new ulong[Size * Size]; var csv = ReadCsv(Path.Combine(input, $"{type}.csv")); var outputDir = Path.Combine(output, type); foreach (var kvp in csv) { using (var tmp = Dlib.LoadImageAsMatrix <RgbPixel>(Path.Combine(input, type, kvp.Key))) { var dets = faceDetector.Operator(tmp); if (!dets.Any()) { Console.WriteLine($"Warning: Failed to detect face from '{kvp}'"); continue; } // Get max size rectangle. It could be better face. var det = dets.Select((val, idx) => new { V = val, I = idx }).Aggregate((max, working) => (max.V.Area > working.V.Area) ? max : working).V; using (var ret = posePredictor.Detect(tmp, det)) using (var chip = Dlib.GetFaceChipDetails(ret, Size, 0d)) using (var faceChips = Dlib.ExtractImageChip <RgbPixel>(tmp, chip)) { var dst = Path.Combine(outputDir, kvp.Key); var dstDir = Path.GetDirectoryName(dst); Directory.CreateDirectory(dstDir); Dlib.SaveJpeg(faceChips, Path.Combine(outputDir, kvp.Key), 100); var index = 0; for (var row = 0; row < Size; row++) { for (var col = 0; col < Size; col++) { var rgb = faceChips[row, col]; r[index] += rgb.Red; g[index] += rgb.Green; b[index] += rgb.Blue; index++; } } } imageCount++; } } using (var mean = new Matrix <RgbPixel>(Size, Size)) { var index = 0; for (var row = 0; row < Size; row++) { for (var col = 0; col < Size; col++) { var red = (double)r[index] / imageCount; var green = (double)g[index] / imageCount; var blue = (double)b[index] / imageCount; var newRed = (byte)Math.Round(red); var newGreen = (byte)Math.Round(green); var newBlue = (byte)Math.Round(blue); mean[row, col] = new RgbPixel(newRed, newGreen, newBlue); index++; } } Dlib.SaveBmp(mean, Path.Combine(output, $"{type}.mean.bmp")); } }
private static void Load(string type, string directory, string meanImage, out IList <Matrix <RgbPixel> > images, out IList <uint> labels) { Matrix <RgbPixel> mean = null; try { if (File.Exists(meanImage)) { mean = Dlib.LoadImageAsMatrix <RgbPixel>(meanImage); } var csv = ReadCsv(Path.Combine(directory, $"{type}.csv")); var imageList = new List <Matrix <RgbPixel> >(); var labelList = new List <uint>(); foreach (var kvp in csv) { var path = Path.Combine(directory, type, kvp.Key); if (!File.Exists(path)) { continue; } using (var tmp = Dlib.LoadImageAsMatrix <RgbPixel>(path)) { if (mean != null) { using (var m = new Matrix <RgbPixel>(Size, Size)) { Dlib.ResizeImage(tmp, m); // ToDo: Support subtract operator on DlibDotNet // var ret = m - mean; var ret = new Matrix <RgbPixel>(Size, Size); for (var row = 0; row < Size; row++) { for (var col = 0; col < Size; col++) { var left = m[row, col]; var right = mean[row, col]; var red = left.Red - right.Red; var green = left.Green - right.Green; var blue = left.Blue - right.Blue; ret[row, col] = new RgbPixel((byte)red, (byte)green, (byte)blue); } } imageList.Add(ret); } } else { var m = new Matrix <RgbPixel>(Size, Size); Dlib.ResizeImage(tmp, m); imageList.Add(m); } labelList.Add(kvp.Value); } } images = imageList; labels = labelList; } finally { mean?.Dispose(); } }
static void Main(string[] args) { /// FaceDetectionWith_API Location[] coord = TestImage(fileName, Model.Hog); /// Face DetectionWith_DLIB using (var fd = Dlib.GetFrontalFaceDetector()) { var img = Dlib.LoadImage <RgbPixel>(fileName); // find all faces in the image var faces = fd.Operator(img); foreach (var face in faces) { // draw a rectangle for each face Dlib.DrawRectangle(img, face, color: new RgbPixel(0, 255, 255), thickness: 4); } Dlib.SaveJpeg(img, outputName); } // The first thing we are going to do is load all our models. First, since we need to // find faces in the image we will need a face detector: using (var detector = Dlib.GetFrontalFaceDetector()) // We will also use a face landmarking model to align faces to a standard pose: (see face_landmark_detection_ex.cpp for an introduction) using (var sp = ShapePredictor.Deserialize("shape_predictor_68_face_landmarks.dat")) // And finally we load the DNN responsible for face recognition. using (var net = DlibDotNet.Dnn.LossMetric.Deserialize("dlib_face_recognition_resnet_model_v1.dat")) using (var img = Dlib.LoadImageAsMatrix <RgbPixel>(fileName)) using (var win = new ImageWindow(img)) { var faces = new List <Matrix <RgbPixel> >(); foreach (var face in detector.Operator(img)) { var shape = sp.Detect(img, face); var faceChipDetail = Dlib.GetFaceChipDetails(shape, 150, 0.25); var faceChip = Dlib.ExtractImageChip <RgbPixel>(img, faceChipDetail); //faces.Add(move(face_chip)); faces.Add(faceChip); win.AddOverlay(face); } if (!faces.Any()) { Console.WriteLine("No faces found in image!"); return; } // This call asks the DNN to convert each face image in faces into a 128D vector. // In this 128D vector space, images from the same person will be close to each other // but vectors from different people will be far apart. So we can use these vectors to // identify if a pair of images are from the same person or from different people. var faceDescriptors = net.Operator(faces); // In particular, one simple thing we can do is face clustering. This next bit of code // creates a graph of connected faces and then uses the Chinese whispers graph clustering // algorithm to identify how many people there are and which faces belong to whom. var edges = new List <SamplePair>(); for (uint i = 0; i < faceDescriptors.Count; ++i) { for (var j = i; j < faceDescriptors.Count; ++j) { // Faces are connected in the graph if they are close enough. Here we check if // the distance between two face descriptors is less than 0.6, which is the // decision threshold the network was trained to use. Although you can // certainly use any other threshold you find useful. var diff = faceDescriptors[i] - faceDescriptors[j]; if (Dlib.Length(diff) < 0.6) { edges.Add(new SamplePair(i, j)); } } } Dlib.ChineseWhispers(edges, 100, out var numClusters, out var labels); // This will correctly indicate that there are 4 people in the image. Console.WriteLine($"number of people found in the image: {numClusters}"); // Отобразим результат в ImageList var winClusters = new List <ImageWindow>(); for (var i = 0; i < numClusters; i++) { winClusters.Add(new ImageWindow()); } var tileImages = new List <Matrix <RgbPixel> >(); for (var clusterId = 0ul; clusterId < numClusters; ++clusterId) { var temp = new List <Matrix <RgbPixel> >(); for (var j = 0; j < labels.Length; ++j) { if (clusterId == labels[j]) { temp.Add(faces[j]); } } winClusters[(int)clusterId].Title = $"face cluster {clusterId}"; var tileImage = Dlib.TileImages(temp); tileImages.Add(tileImage); winClusters[(int)clusterId].SetImage(tileImage); } // Finally, let's print one of the face descriptors to the screen. using (var trans = Dlib.Trans(faceDescriptors[0])) { Console.WriteLine($"face descriptor for one face: {trans}"); // It should also be noted that face recognition accuracy can be improved if jittering // is used when creating face descriptors. In particular, to get 99.38% on the LFW // benchmark you need to use the jitter_image() routine to compute the descriptors, // like so: var jitterImages = JitterImage(faces[0]).ToArray(); var ret = net.Operator(jitterImages); using (var m = Dlib.Mat(ret)) using (var faceDescriptor = Dlib.Mean <float>(m)) using (var t = Dlib.Trans(faceDescriptor)) { Console.WriteLine($"jittered face descriptor for one face: {t}"); // If you use the model without jittering, as we did when clustering the bald guys, it // gets an accuracy of 99.13% on the LFW benchmark. So jittering makes the whole // procedure a little more accurate but makes face descriptor calculation slower. Console.WriteLine("hit enter to terminate"); Console.ReadKey(); foreach (var jitterImage in jitterImages) { jitterImage.Dispose(); } foreach (var tileImage in tileImages) { tileImage.Dispose(); } foreach (var edge in edges) { edge.Dispose(); } foreach (var descriptor in faceDescriptors) { descriptor.Dispose(); } foreach (var face in faces) { face.Dispose(); } } } } System.Console.ReadLine(); }