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