c#中 在webapi中 使用opencvSharp4以及ssim算法 完成人脸检测 以此实现以图搜图

通过把上传的图片中的人物人脸剪切出来跟图库作比较 
最终跟相似度做比较 把符合的筛选出来
优化
1.ssim算法消耗进程内存过多
2.opencvsharp可以考虑替换成开源框架FaceRecognitionDotNet

整体代码如下

using Emgu.CV;
using Emgu.CV.Structure;
using Microsoft.AspNetCore.Mvc;
using OpenCvSharp;
using System.Drawing;
using CascadeClassifier = Emgu.CV.CascadeClassifier;
using Mat = OpenCvSharp.Mat;
using Size = System.Drawing.Size;

namespace WebApplication5.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet(Name = "GetWeatherForecast")]
        public IEnumerable<WeatherForecast> Get()
        {
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

        /// <summary>
        /// 剪切图片中的人脸并保存
        /// </summary>
        [HttpGet(Name = "Getface")]
        public void GetFace()
        {
            var face = new CascadeClassifier(@"C:\Users\2023\Desktop\haarcascade_frontalface_alt.xml");
            //加载要识别的图片
            var img = new Image<Bgr, byte>(@"C:\Users\2023\Desktop\test\38.png");

            //在这一步就已经识别出来了,返回的是人脸所在的位置和大小
            var facesDetected = face.DetectMultiScale(img, 1.2, 10, new Size(60, 60));

            //循环把人脸部分切出来并保存
            int count = 0;
            var b = img.ToBitmap();

            foreach (var item in facesDetected)
            {
                count++;
                var bmpOut = new Bitmap(item.Width, item.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
                var g = Graphics.FromImage(bmpOut);
                g.DrawImage(b, new Rectangle(0, 0, item.Width, item.Height), new Rectangle(item.X, item.Y, item.Width, item.Height), GraphicsUnit.Pixel);
                g.Dispose();
                
                bmpOut.Save($"{count}.png", System.Drawing.Imaging.ImageFormat.Png);
                bmpOut.Dispose();
            }

            //释放资源退出
            b.Dispose();
            img.Dispose();
            face.Dispose();
        }


        /// <summary>
        /// 根据生成的人脸进行比对并输出符合条件的图片
        /// </summary>
        [HttpGet(Name = "GetResultImage")]
        public void getResultImage()
        {
            
            var localImages = Directory.GetFiles(@"C:\Users\2023\Desktop\test", "*.png");
            String generatedImage = @"C:\Users\2023\Desktop\6.png";
            double Minshold = 0.38731;
            double Maxhold = 0.4401;

            Parallel.ForEach(localImages, new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount },
                (i) =>
                {
                    // 进行比对的代码
                    double ssim = (double)CompareImagesSSIM(i, generatedImage);

                    if (ssim >= Minshold && ssim <= Maxhold)
                    {
                        var outputDirectory = @"C:\Users\2023\Desktop\testPro\newDir";
                        if (!Directory.Exists(outputDirectory))
                        {
                            Directory.CreateDirectory(outputDirectory);
                        }
                        var outputFilePath = Path.Combine(outputDirectory, Path.GetFileName(i));

                        using (var sourceStream = new FileStream(i, FileMode.Open))
                        using (var destinationStream = new FileStream(outputFilePath, FileMode.Create))
                        {
                            sourceStream.CopyTo(destinationStream);
                        }
                    }
                }
            );
        }








        /// <summary>
        /// 计算ssim精确度
        /// </summary>
        /// <param name="imgFile1"></param>
        /// <param name="imgFile2"></param>
        /// <returns></returns>
        [HttpPost(Name = "GetSsim")]
        public Scalar CompareImagesSSIM(string imgFile1, string imgFile2)
        {
            using (var image1 = Cv2.ImRead(imgFile1))
            using (var image2Tmp = Cv2.ImRead(imgFile2))
            {
                // 将两个图片处理成同样大小,否则会有错误: 
                var image2 = new Mat();
                Cv2.Resize(image2Tmp, image2, new OpenCvSharp.Size(image1.Size().Width, image1.Size().Height));
                double C1 = 6.5025, C2 = 58.5225;
                var validImage1 = new Mat();
                var validImage2 = new Mat();
                Parallel.Invoke(
                    () =>{  image1.ConvertTo(validImage1, MatType.CV_32F); },
                   () => { image2.ConvertTo(validImage2, MatType.CV_32F); }

                );
                //image1.ConvertTo(validImage1, MatType.CV_32F); //数据类型转换为 float,防止后续计算出现错误
                //image2.ConvertTo(validImage2, MatType.CV_32F);

                Mat image1_1 = validImage1.Mul(validImage1); //图像乘积
                Mat image2_2 = validImage2.Mul(validImage2);
                Mat image1_2 = validImage1.Mul(validImage2);

               
               Mat gausBlur1 = new Mat(), gausBlur2 = new Mat(), gausBlur12 = new Mat();
                Cv2.GaussianBlur(validImage1, gausBlur1, new OpenCvSharp.Size(11, 11), 1.5); //高斯卷积核计算图像均值
                Cv2.GaussianBlur(validImage2, gausBlur2, new OpenCvSharp.Size(11, 11), 1.5);
                Cv2.GaussianBlur(image1_2, gausBlur12, new OpenCvSharp.Size(11, 11), 1.5);

                Parallel.Invoke(
                   () => { }
                   );

                Mat imageAvgProduct = gausBlur1.Mul(gausBlur2); //均值乘积
                Mat u1Squre = gausBlur1.Mul(gausBlur1); //各自均值的平方
                Mat u2Squre = gausBlur2.Mul(gausBlur2);

                Mat imageConvariance = new Mat(), imageVariance1 = new Mat(), imageVariance2 = new Mat();
                Mat squreAvg1 = new Mat(), squreAvg2 = new Mat();
                Cv2.GaussianBlur(image1_1, squreAvg1, new OpenCvSharp.Size(11, 11), 1.5); //图像平方的均值
                Cv2.GaussianBlur(image2_2, squreAvg2, new OpenCvSharp.Size(11, 11), 1.5);

                imageConvariance = gausBlur12 - gausBlur1.Mul(gausBlur2);// 计算协方差
                imageVariance1 = squreAvg1 - gausBlur1.Mul(gausBlur1); //计算方差
                imageVariance2 = squreAvg2 - gausBlur2.Mul(gausBlur2);

                var member = ((2 * gausBlur1.Mul(gausBlur2) + C1).Mul(2 * imageConvariance + C2));
                var denominator = ((u1Squre + u2Squre + C1).Mul(imageVariance1 + imageVariance2 + C2));
                Mat ssim = new Mat();
                Cv2.Divide(member, denominator, ssim);
                var sclar = Cv2.Mean(ssim);

                validImage1.Dispose();
                validImage2.Dispose();
                image1_1.Dispose();
                image2_2.Dispose();
                image1_2.Dispose();
                gausBlur1.Dispose();
                gausBlur2.Dispose();
                gausBlur12.Dispose();
                imageAvgProduct.Dispose();
                u1Squre.Dispose();
                u2Squre.Dispose();
                imageConvariance.Dispose();
                imageVariance1.Dispose();
                imageVariance2.Dispose();
                squreAvg1.Dispose();
                squreAvg2.Dispose();
                ssim.Dispose();

                GC.Collect();
                return sclar;  // 变化率,即差异
            }

        }

    }

}
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐