当前位置:   article > 正文

C# OpenCvSharp DNN FreeYOLO 人脸检测&人脸图像质量评估_opencv 人脸图像质量评估 c#

opencv 人脸图像质量评估 c#

 目录

效果

模型信息

yolo_free_huge_widerface_192x320.onnx

face-quality-assessment.onnx

项目

代码

frmMain.cs

FreeYoloFace

FaceQualityAssessment.cs

下载


C# OpenCvSharp DNN FreeYOLO 人脸检测&人脸图像质量评估

效果

模型信息

yolo_free_huge_widerface_192x320.onnx


Inputs
-------------------------
name:input
tensor:Float[1, 3, 192, 320]
---------------------------------------------------------------

Outputs
-------------------------
name:output
tensor:Float[1, 1260, 6]
---------------------------------------------------------------

face-quality-assessment.onnx

Inputs
-------------------------
name:input
tensor:Float[1, 3, 112, 112]
---------------------------------------------------------------

Outputs
-------------------------
name:quality
tensor:Float[1, 10]
---------------------------------------------------------------

项目

代码

frmMain.cs

using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace OpenCvSharp_DNN_Demo
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        string fileFilter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
        string image_path = "";

        DateTime dt1 = DateTime.Now;
        DateTime dt2 = DateTime.Now;

        StringBuilder sb = new StringBuilder();

        Mat image;
        Mat result_image;

        FaceQualityAssessment fqa = new FaceQualityAssessment("model/face-quality-assessment.onnx");
        FreeYoloFace face = new FreeYoloFace("model/yolo_free_huge_widerface_192x320.onnx");

        private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = fileFilter;
            if (ofd.ShowDialog() != DialogResult.OK) return;

            pictureBox1.Image = null;
            pictureBox2.Image = null;
            textBox1.Text = "";

            image_path = ofd.FileName;
            pictureBox1.Image = new Bitmap(image_path);
            image = new Mat(image_path);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            image_path = "test_img/1.jpg";
            pictureBox1.Image = new Bitmap(image_path);
        }

        private unsafe void button2_Click(object sender, EventArgs e)
        {
            if (image_path == "")
            {
                return;
            }
            textBox1.Text = "检测中,请稍等……";
            if (pictureBox2.Image != null)
            {
                pictureBox2.Image.Dispose();
            }
            pictureBox2.Image = null;
            sb.Clear();
            Application.DoEvents();

            image = new Mat(image_path);

            dt1 = DateTime.Now;
            List<Face> ltFace = face.Detect(image);
            dt2 = DateTime.Now;

            if (ltFace.Count > 0)
            {
                sb.AppendLine("推理耗时:" + (dt2 - dt1).TotalMilliseconds + "ms");
                result_image = image.Clone();
                foreach (var item in ltFace)
                {
                    Mat crop_img = new Mat(image, item.rect);
                    float fqa_prob_mean = fqa.Detect(crop_img);
                    crop_img.Dispose();
                    Cv2.Rectangle(result_image, new OpenCvSharp.Point(item.rect.X, item.rect.Y), new OpenCvSharp.Point(item.rect.X + item.rect.Width, item.rect.Y + item.rect.Height), new Scalar(0, 0, 255), 2);
                    string label = "prob:" + item.prob.ToString("0.00") + " fqa_score:" + fqa_prob_mean.ToString("0.00");
                    sb.AppendLine(label);
                    Cv2.PutText(result_image, label, new OpenCvSharp.Point(item.rect.X, item.rect.Y - 5), HersheyFonts.HersheySimplex, 1, new Scalar(0, 0, 255), 2);
                }
                pictureBox2.Image = new Bitmap(result_image.ToMemoryStream());
                textBox1.Text = sb.ToString();
            }
            else
            {
                textBox1.Text = "未检测到人脸";
            }
        }

        private void pictureBox2_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox2.Image);
        }

        private void pictureBox1_DoubleClick(object sender, EventArgs e)
        {
            Common.ShowNormalImg(pictureBox1.Image);
        }
    }
}

FreeYoloFace.cs

  1. using OpenCvSharp.Dnn;
  2. using OpenCvSharp;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. namespace OpenCvSharp_DNN_Demo
  7. {
  8. public class FreeYoloFace
  9. {
  10. float confThreshold;
  11. float nmsThreshold;
  12. int num_stride = 3;
  13. float[] strides = new float[3] { 8.0f, 16.0f, 32.0f };
  14. string modelpath;
  15. int inpHeight;
  16. int inpWidth;
  17. List<string> class_names;
  18. int num_class;
  19. Net opencv_net;
  20. Mat BN_image;
  21. Mat image;
  22. public FreeYoloFace(string modelpath)
  23. {
  24. opencv_net = CvDnn.ReadNetFromOnnx(modelpath);
  25. class_names = new List<string> { "face" };
  26. num_class = 1;
  27. confThreshold = 0.8f;
  28. nmsThreshold = 0.5f;
  29. inpHeight = 192;
  30. inpWidth = 320;
  31. }
  32. unsafe public List<Face> Detect(Mat image)
  33. {
  34. List<Face> ltFace = new List<Face>();
  35. float ratio = Math.Min(1.0f * inpHeight / image.Rows, 1.0f * inpWidth / image.Cols);
  36. int neww = (int)(image.Cols * ratio);
  37. int newh = (int)(image.Rows * ratio);
  38. Mat dstimg = new Mat();
  39. Cv2.Resize(image, dstimg, new OpenCvSharp.Size(neww, newh));
  40. Cv2.CopyMakeBorder(dstimg, dstimg, 0, inpHeight - newh, 0, inpWidth - neww, BorderTypes.Constant);
  41. BN_image = CvDnn.BlobFromImage(dstimg);
  42. //配置图片输入数据
  43. opencv_net.SetInput(BN_image);
  44. //模型推理,读取推理结果
  45. Mat[] outs = new Mat[1] { new Mat() };
  46. string[] outBlobNames = opencv_net.GetUnconnectedOutLayersNames().ToArray();
  47. opencv_net.Forward(outs, outBlobNames);
  48. int num_proposal = outs[0].Size(1);
  49. int nout = outs[0].Size(2);
  50. float* pdata = (float*)outs[0].Data;
  51. List<float> confidences = new List<float>();
  52. List<Rect> boxes = new List<Rect>();
  53. List<int> classIds = new List<int>();
  54. for (int n = 0; n < num_stride; n++)
  55. {
  56. int num_grid_x = (int)Math.Ceiling(inpWidth / strides[n]);
  57. int num_grid_y = (int)Math.Ceiling(inpHeight / strides[n]);
  58. for (int i = 0; i < num_grid_y; i++)
  59. {
  60. for (int j = 0; j < num_grid_x; j++)
  61. {
  62. float box_score = pdata[4];
  63. int max_ind = 0;
  64. float max_class_socre = 0;
  65. for (int k = 0; k < num_class; k++)
  66. {
  67. if (pdata[k + 5] > max_class_socre)
  68. {
  69. max_class_socre = pdata[k + 5];
  70. max_ind = k;
  71. }
  72. }
  73. max_class_socre = max_class_socre * box_score;
  74. max_class_socre = (float)Math.Sqrt(max_class_socre);
  75. if (max_class_socre > confThreshold)
  76. {
  77. float cx = (0.5f + j + pdata[0]) * strides[n]; //cx
  78. float cy = (0.5f + i + pdata[1]) * strides[n]; //cy
  79. float w = (float)(Math.Exp(pdata[2]) * strides[n]); //w
  80. float h = (float)(Math.Exp(pdata[3]) * strides[n]); //h
  81. float xmin = (float)((cx - 0.5 * w) / ratio);
  82. float ymin = (float)((cy - 0.5 * h) / ratio);
  83. float xmax = (float)((cx + 0.5 * w) / ratio);
  84. float ymax = (float)((cy + 0.5 * h) / ratio);
  85. int left = (int)((cx - 0.5 * w) / ratio);
  86. int top = (int)((cy - 0.5 * h) / ratio);
  87. int width = (int)(w / ratio);
  88. int height = (int)(h / ratio);
  89. confidences.Add(max_class_socre);
  90. boxes.Add(new Rect(left, top, width, height));
  91. classIds.Add(max_ind);
  92. }
  93. pdata += nout;
  94. }
  95. }
  96. }
  97. int[] indices;
  98. CvDnn.NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, out indices);
  99. for (int ii = 0; ii < indices.Length; ++ii)
  100. {
  101. int idx = indices[ii];
  102. Rect box = boxes[idx];
  103. ltFace.Add(new Face(box, confidences[idx]));
  104. }
  105. outs[0].Dispose();
  106. BN_image.Dispose();
  107. dstimg.Dispose();
  108. return ltFace;
  109. }
  110. }
  111. }

FaceQualityAssessment.cs

  1. using OpenCvSharp;
  2. using OpenCvSharp.Dnn;
  3. using System.Linq;
  4. namespace OpenCvSharp_DNN_Demo
  5. {
  6. public class FaceQualityAssessment
  7. {
  8. Net net;
  9. int inpWidth = 112;
  10. int inpHeight = 112;
  11. float[] mean = new float[] { 0.5f, 0.5f, 0.5f };
  12. float[] std = new float[] { 0.5f, 0.5f, 0.5f };
  13. public FaceQualityAssessment(string modelpath)
  14. {
  15. net = CvDnn.ReadNetFromOnnx(modelpath);
  16. }
  17. unsafe public float Detect(Mat cropped)
  18. {
  19. Mat rgbimg = new Mat();
  20. Cv2.CvtColor(cropped, rgbimg, ColorConversionCodes.BGR2RGB);
  21. Cv2.Resize(rgbimg, rgbimg, new Size(inpWidth, inpHeight));
  22. Mat normalized_mat = Normalize(rgbimg);
  23. Mat blob = CvDnn.BlobFromImage(normalized_mat);
  24. //配置图片输入数据
  25. net.SetInput(blob);
  26. //模型推理,读取推理结果
  27. Mat[] outs = new Mat[1] { new Mat() };
  28. string[] outBlobNames = net.GetUnconnectedOutLayersNames().ToArray();
  29. net.Forward(outs, outBlobNames);
  30. float* pdata = (float*)outs[0].Data; //形状1x10
  31. int length = outs[0].Size(1);
  32. float fqa_prob_mean = 0;
  33. for (int i = 0; i < length; i++)
  34. {
  35. fqa_prob_mean += pdata[i];
  36. }
  37. fqa_prob_mean /= length;
  38. rgbimg.Dispose();
  39. normalized_mat.Dispose();
  40. blob.Dispose();
  41. outs[0].Dispose();
  42. return fqa_prob_mean;
  43. }
  44. Mat Normalize(Mat src)
  45. {
  46. Mat[] bgr = src.Split();
  47. for (int i = 0; i < bgr.Length; ++i)
  48. {
  49. bgr[i].ConvertTo(bgr[i], MatType.CV_32FC1, 1.0 / (255.0 * std[i]), (0.0 - mean[i]) / std[i]);
  50. }
  51. Cv2.Merge(bgr, src);
  52. foreach (Mat channel in bgr)
  53. {
  54. channel.Dispose();
  55. }
  56. return src;
  57. }
  58. }
  59. }

下载

源码下载

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/99712
推荐阅读
相关标签
  

闽ICP备14008679号