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")); } }