C#使用Emgu CV來進行圖片人臉檢測

来源:https://www.cnblogs.com/wdw984/archive/2019/10/29/11758163.html
-Advertisement-
Play Games

項目需求:某市級組織考試,在考試前需審核考生採集表中的考生照片是否合格,由於要審核的考生信息採集表有很多,原先進行的是手動人工審核,比較費時費力,審核的要求也很簡單,並不判斷考生是否是圖片本人(身份驗證有另外一套程式來進行),只是看考生採集表中考生頭像是否是人臉(是否存在辨識不清楚,不是人臉)。因此 ...


項目需求:某市級組織考試,在考試前需審核考生採集表中的考生照片是否合格,由於要審核的考生信息採集表有很多,原先進行的是手動人工審核,比較費時費力,審核的要求也很簡單,並不判斷考生是否是圖片本人(身份驗證有另外一套程式來進行),只是看考生採集表中考生頭像是否是人臉(是否存在辨識不清楚,不是人臉)。因此提出需求,看是否能用程式來檢測考生信息採集表中的照片,只需找出來疑似不是人臉的考生所在文檔位置(pdf文檔)即可,存疑的考生再由人工進行審核。

PDF文檔中有很多頁,每一頁都是如圖中的結構。

 

經過百度摸索,採用了C#+WPF+Spire.PDF+Emgu CV+MvvmLight來進行人臉判斷的技術選型。

Emgu CV(https://sourceforge.net/projects/emgucv/files/emgucv/)是.NET平臺下對OpenCV圖像處理庫的封裝,也就是.NET版的
OpenCV的全稱是:Open Source Computer Vision Library。OpenCV是一個基於(開源)發行的跨平臺電腦視覺庫,可以運行在Linux、Windows和Mac OS操作系統上。Emgu CV官方帶的有訓練過的人臉識別模板,可以直接使用。

Spire.PDF可以來讀取PDF文檔,同時可以讀取到PDF文檔中的圖片。

MvvmLight是WPF可以使用的一種MVVM模式的實現框架。

項目技術選型確定以後,下麵就是代碼的編寫。

項目引用Emgu CV、Spire.PDF、MvvmLight

從官網下載Emgu CV後,我們把它項目中的haarcascade_eye.xml、haarcascade_frontalface_alt.xml兩個訓練過的人臉識別模板放到bin/debug下,供Emgu CV使用時調用。

引用MvvmLight後,會自動在項目中創建ViewModel目錄,我們在此目錄中新建一個Pdf2FaceInfoModel.cs類,用來做為檢測結果的通知類。

using System.ComponentModel;
 
namespace Pdf2Face.ViewModel
{
    public class Pdf2FaceInfoModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
 
        private string pdfName { get; set; }
        /// <summary>
        /// Pdf文件名
        /// </summary>
        public string PdfName
        {
            get => pdfName;
            set
            {
                pdfName = value;
                PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("PdfName"));
            }
        }
 
        private int pdfImgCount { get; set; } = 0;
        /// <summary>
        /// Pdf中圖片數量
        /// </summary>
        public int PdfImgCount
        {
            get => pdfImgCount;
            set
            {
                pdfImgCount = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PdfImgCount"));
            }
        }
 
        private int pdfFaceCount { get; set; } = 0;
        /// <summary>
        /// Pdf中人臉數量
        /// </summary>
        public int PdfFaceCount
        {
            get => pdfFaceCount;
            set
            {
                pdfFaceCount = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PdfFaceCount"));
            }
        }
 
        private string pdfFaceSuccess { get; set; } ="否";
        /// <summary>
        /// 數量相對是否存疑 0 正常 1存疑
        /// </summary>
        public string PdfFaceSuccess
        {
            get => pdfFaceSuccess;
            set
            {
                pdfFaceSuccess = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PdfFaceSuccess"));
            }
        }
    }
}

主程式只有一個界面,界面兩個按鈕,一個用來選擇要檢測pdf所在文件夾,一個用來開始檢測。

主程式代碼:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Emgu.CV;
using Emgu.CV.Structure;
using Microsoft.WindowsAPICodePack.Dialogs;
using Pdf2Face.ViewModel;
using Spire.Pdf;
 
namespace Pdf2Face
{
    /// <summary>
    /// 人臉檢測功能的交互邏輯
    /// </summary>
    public partial class MainWindow : Window
    {
        private string _pdfDirPath;
        private readonly string _pdfFaceSaveDir;
        private readonly ObservableCollection<Pdf2FaceInfoModel> facelist = new ObservableCollection<Pdf2FaceInfoModel>();
 
        public MainWindow()
        {
            InitializeComponent();
            Thread.Sleep(10000);
            dataGrid.ItemsSource = facelist;
            _pdfFaceSaveDir = $"{AppDomain.CurrentDomain.BaseDirectory}face";
            if (!Directory.Exists(_pdfFaceSaveDir))
            {
                Directory.CreateDirectory(_pdfFaceSaveDir);
            }
        }
        /// <summary>
        /// 選擇Pdf所在目錄
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnChooseDir_OnClick(object sender, RoutedEventArgs e)
        {
            using (var folderBrowser = new CommonOpenFileDialog())
            {
                folderBrowser.IsFolderPicker = true;
                folderBrowser.Multiselect = false;
                folderBrowser.Title = "選擇考生照片所在文件夾";
                if (folderBrowser.ShowDialog(GetWindow(this)) != CommonFileDialogResult.Ok) return;
                _pdfDirPath = folderBrowser.FileName;
                txtBlockPath.Text = _pdfDirPath;
            }
        }
        /// <summary>
        /// 人臉識別檢測
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtnCheck_OnClick(object sender, RoutedEventArgs e)
        {
            if (string.IsNullOrEmpty(_pdfDirPath) || !Directory.Exists(_pdfDirPath))
            {
                MessageBox.Show("目錄無法訪問。", "錯誤", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
 
            var pdfs = FileSearch(_pdfDirPath, "*.pdf", SearchOption.AllDirectories,
                x => x.Length > 6);
            if (pdfs.Length == 0)
            {
                MessageBox.Show("指定的目錄中沒有發現PDF文件。", "錯誤", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }
 
            txtBlockInfo.Text = $"Pdf文件數量{pdfs.Length}";
            var doc = new PdfDocument();
 
            Dispatcher?.InvokeAsync(async () =>
            {
                await Task.Run(() =>
                {
                    foreach (var pdf in pdfs)
                    {
                        doc.LoadFromFile(pdf);
                        var pagenum = 1;
 
                        foreach (PdfPageBase page in doc.Pages)
                        {
                            var newPdfFaceSaveDir = $"{_pdfFaceSaveDir}\\{pdf.Substring(pdf.LastIndexOf('\\') + 1)}";
                            if (page.ExtractImages() != null)
                            {
                                if (!Directory.Exists(newPdfFaceSaveDir))
                                {
                                    Directory.CreateDirectory(newPdfFaceSaveDir);
                                }
                                var images = new List<Image>();
                                var model = new Pdf2FaceInfoModel
                                {
                                    PdfName = $"{pdf.Substring(pdf.LastIndexOf('\\') + 1)}_第{pagenum}頁"
                                };
                                Dispatcher?.Invoke(() =>
                                {
                                    facelist.Add(model);
 
                                });
                                var c = 0;
                                foreach (var image in page.ExtractImages())
                                {
                                    images.Add(image);
                                    var filename = $"{newPdfFaceSaveDir}\\{pagenum}_{c}.png";
                                    image.Save(filename, ImageFormat.Png);
 
                                    #region 人臉判斷
                                    //檢測是否是人臉
                                    //如果支持用顯卡,則用顯卡運算
                                    CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;
                                    //構建級聯分類器,利用已經訓練好的數據,識別人臉
                                    var face = new CascadeClassifier("haarcascade_frontalface_alt.xml");
                                    var eyes = new CascadeClassifier("haarcascade_eye.xml");
                                    //載入要識別的圖片
                                    var img = new Image<Bgr, byte>(filename);
                                    var img2 = new Image<Gray, byte>(img.ToBitmap());
 
                                    //把圖片從彩色轉灰度
                                    CvInvoke.CvtColor(img, img2, Emgu.CV.CvEnum.ColorConversion.Bgr2Gray);
                                    //亮度增強
                                    CvInvoke.EqualizeHist(img2, img2);
                                    //返回的是人臉所在的位置和大小
                                    var facesDetected = face.DetectMultiScale(img2, 1.1, 10, new System.Drawing.Size(50, 50));                                    
 
                                    if (facesDetected.Length > 0)
                                    {
                                        model.PdfFaceCount += facesDetected.Length;
                                        model.PdfFaceSuccess = facesDetected.Length > 1 ? "是" : "否";
                                        //刪除圖片,留下的都是無法正確識別的
                                        try
                                        {
                                            File.Delete(filename);
                                        }
                                        catch (Exception exception)
                                        {
                                            //
                                        }
                                    }
 
                                    img.Dispose();
                                    img2.Dispose();
                                    face.Dispose();
                                    #endregion
 
                                    c += 1;
                                }
                                model.PdfImgCount = images.Count;
                            }
                            pagenum += 1;
                        }
                        doc.Close();
                    }
 
                });
            });
        }
 
        private string[] FileSearch(string directoryPath, string searchFilter, SearchOption option, Func<string, bool> func)
        {
            if (!Directory.Exists(directoryPath)) return null;
            var s = Directory.GetFiles(directoryPath, searchFilter, option).Where(func).ToArray();
            return s;
        }
 
        private void MainWindow_OnClosing(object sender, CancelEventArgs e)
        {
            Application.Current.Shutdown(0);
        }
    }
}

程式運行效果:

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 場景 Winform控制項-DevExpress18下載安裝註冊以及在VS中使用: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100061243 在上面已經成功安裝DevExpress的前提下,要顯示頁面佈局效果為Tab頁效果, ...
  • 【推薦閱讀我的最新的Core版文章,是最全的介紹:C#_.NetCore_Web項目_EXCEL數據導出】 需要引用NPOI的Nuget包:NPOI-v2.4.1 B-1:EXCEL數據導入--C#獲取數據: ...
  • A-1:EXCEL模板導出 非常簡單,將EXCEL模板上傳到項目中後,將其瀏覽URL保存下來(excelUrl),然後: 或者使用<a href="excelUrl"></a>都行。 ...
  • ASP.NET簡介 簡單來說,ASP.NET 是一個使用 HTML、CSS、JavaScript 和伺服器腳本創建網頁和網站的開發框架。 微軟在2001年開發的第一個版本的ASP.NET,是一種建立在.NET之上的Web運行環境。藉助於ASP.NET,可以創造出內容豐富的、動態的、個性化的Web站點 ...
  • 很早之前就玩過VS裡面的code snippet,相當方便。 今天在用prop自動屬性代碼時,無意中用了一下propa,然後就自動出來了依賴屬性的代碼片段,太方便了,尤其是對於WPF新手來說,比如我這樣的。 ...
  • Aspose.PDF for .NET是一種高級PDF處理和解析API,用於在跨平臺應用程式中執行文檔管理和操作任務。API可以輕鬆用於生成,修改,轉換,渲染,保護和列印PDF文檔,而無需使用Adobe Acrobat。此外,還提供PDF壓縮選項,表格創建和操作,圖形和圖像功能,廣泛的超鏈接功能,印 ...
  • Quartz.Net 刪除Job 來博客園的第一篇文章先寫個簡單的,希望能幫助到大家。 步入正題: Quartz.Net有三個重要的概念,分別是 Scheduler 、Job 、Trigger。 Scheduler包含Job和Trigger。 如果要刪除一個正在運行的Job,需要在Schedule中 ...
  • Aspose.PSD是高級PSD文件格式操作API,沒有任何Adobe Photoshop依賴項。API允許創建或編輯Photoshop文件,並提供更新圖層屬性,添加水印,執行圖形操作或將一種文件格式轉換為另一種文件的功能。 Aspose.PSD for .NET支持PSD和PSB文件格式進行載入和 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...