C#/.net/DotNet/Emgu.CV裁剪照片头像

头像裁剪有利于人脸识别批量照片预处理,安防领域可以快速通过视频定位人脸,进行抓拍,做人脸识别相关功能的可能会应用到人脸裁剪,以下是我在实践中应用的代码,如有需要复制粘贴即可使用。

using Emgu.CV;
using Emgu.CV.Structure;
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;

namespace CutFace
{
    class Program
    {
        static void Main(string[] args)
        {
            FaceClassifier = InitFaceClassifier();
            CutFace($@"{RootPath}\images", $@"{RootPath}\faceimages");
        }

        /// <summary>
        /// 根路径
        /// </summary>
        public static string RootPath = AppDomain.CurrentDomain.BaseDirectory;

        /// <summary>
        /// 人脸级联分类器
        /// </summary>
        public static CascadeClassifier FaceClassifier { get; set; }

        /// <summary>
        /// 初始化人脸级联分类器
        /// </summary>
        public static CascadeClassifier InitFaceClassifier()
        {
            //判断opencv相关文件是否存在,不存在根据系统类型创建相关文件
            if (!File.Exists($@"{RootPath}\cvextern.dll"))
            {
                var dir = $@"{RootPath}\opencv";

                string zip = Directory.GetFiles(dir).Where(m => Environment.Is64BitProcess ? m.Contains("x64.zip") : m.Contains("x86.zip")).FirstOrDefault();
                if (!string.IsNullOrEmpty(zip))
                {
                    //将压缩包解压到根目录
                    new FastZip().ExtractZip(zip, RootPath, null);
                }
            }

            //如果支持用显卡,则用显卡运算
            CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;

            //构建级联分类器,利用已经训练好的数据,识别人脸
            return new CascadeClassifier($@"{RootPath}\opencv\haarcascade_frontalface_alt.xml");
        }

        /// <summary>
        /// 裁剪人脸
        /// </summary>
        /// <param name="srcPath">源路径</param>
        /// <param name="outPath">输出路径</param>
        public static void CutFace(string srcPath, string outPath)
        {
            if (!Directory.Exists(outPath))
            {
                Directory.CreateDirectory(outPath);
            }

            var files = Directory.GetFiles(srcPath);

            int fcount = 0;

            foreach (var f in files)
            {
                //加载要识别的图片
                using (var img = new Image<Bgr, byte>(f))
                {
                    using (var img2 = img.Clone())
                    {
                        //把图片从彩色转灰度
                        CvInvoke.CvtColor(img, img2, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);

                        //亮度增强
                        CvInvoke.EqualizeHist(img2, img2);

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

                        //循环把人脸部分切出来并保存
                        foreach (var item in facesDetected)
                        {
                            fcount++;

                            //彩照用img,黑白照用img2
                            using (MemoryStream ms = new MemoryStream(img.ToJpegData(80)))
                            {
                                using (Image b = Image.FromStream(ms))
                                {
                                    using (var bmpOut = new Bitmap(200, 200, PixelFormat.Format32bppRgb))
                                    {
                                        using (var g = Graphics.FromImage(bmpOut))
                                        {
                                            g.DrawImage(b, new Rectangle(0, 0, 200, 200), new Rectangle(item.X - 30, item.Y - 30, item.Width + 60, item.Height + 60), GraphicsUnit.Pixel);
                                        }
                                        bmpOut.Save(f.Replace(srcPath, outPath), ImageFormat.Jpeg);
                                    }

                                    //只保留最先识别出来的人脸
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (fcount > 0)
            {
                Console.WriteLine("头像处理成功!");
            }
            else
            {
                Console.WriteLine("没有头像照片可供处理!");
            }

            Console.ReadLine();
        }
    }
}

  

posted @ 2021-01-03 21:03  你好创造者  阅读(383)  评论(0编辑  收藏  举报