OpenCVの人脸检测

MainWindow.xaml

<Window x:Class="Splash.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="OpenCVの人脸检测" Icon="OpenCV.ico" WindowStartupLocation="CenterScreen" WindowState="Maximized" Loaded="Window_Loaded" Closing="Window_Closing">
    <Grid>
        <TabControl Margin="4" SelectionChanged="TabControl_SelectionChanged">
            <TabItem Header="视频人脸检测" Padding="8" Width="200">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>

                    <Grid Grid.Row="0">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition />
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>

                        <Label Grid.Column="0" Margin="4" Content="选择摄像头" VerticalContentAlignment="Center"/>
                        <ComboBox Grid.Column="1" Margin="4" HorizontalAlignment="Left" VerticalContentAlignment="Center" Width="320" Name="ComboBoxCameraDevices"/>
                        <Button Grid.Column="2" Margin="4" Padding="16,8" Foreground="Brown" Content="开启摄像头" Name="ButtonCaputre" Click="ButtonCaputre_Click"/>
                    </Grid>

                    <ScrollViewer Grid.Row="1" Margin="4" Background="Black" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
                        <Image Stretch="None" Margin="4" Name="ImageVideo"/>
                    </ScrollViewer>
                </Grid>
            </TabItem>

            <TabItem Header="图像人脸检测" Padding="8" Width="200">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>

                    <Button Grid.Row="0" Margin="4" Padding="16,8" HorizontalAlignment="Center" Foreground="Brown" Content="选择图像…" Name="ButtonSelect" Click="ButtonSelect_Click"/>
                    <ScrollViewer Grid.Row="1" Margin="4" Background="Black" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
                        <Image Stretch="None" Margin="4" Name="ImagePhoto"/>
                    </ScrollViewer>
                </Grid>
            </TabItem>
        </TabControl>
    </Grid>
</Window>

MainWindow.xaml.cs

/* ----------------------------------------------------------
* 文件名称:MainWindow.xaml.cs
*
* 作者:秦建辉
*
* 微信:splashcn
*
* 博客:http://www.firstsolver.com/wordpress/
*
* 开发环境:
*      Visual Studio V2017
*      .NET Framework 4.7.2
*      OpenCvSharp 4.0.30319
*
* 版本历史:
*		V1.0    2018年12月27日
*				OpenCVの人脸检测
* ---------------------------------------------------------- */
using Com.FirstSolver.Splash;
using Newtonsoft.Json.Linq;
using OpenCvSharp.Extensions;
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows;

namespace Splash
{
    public partial class MainWindow : System.Windows.Window
    {
        /// <summary>
        /// 人脸检测是否正在进行
        /// </summary>
        private bool IsRunning = false;

        /// <summary>
        /// 视频捕获设备
        /// </summary>
        private OpenCvSharp.VideoCapture Capture = null;

        /// <summary>
        /// 是否停止人脸检测
        /// </summary>
        private volatile bool ShouldStop = true;

        /// <summary>
        /// 是否停止等待下一帧
        /// </summary>
        private ManualResetEvent WakeupResetEvent = new ManualResetEvent(true);

        /// <summary>
        /// 眼睛分类器
        /// </summary>
        private OpenCvSharp.CascadeClassifier EyeClassifier = null;

        /// <summary>
        /// 人脸框分类器
        /// </summary>
        private OpenCvSharp.CascadeClassifier FaceClassifier = null;

        public MainWindow()
        {
            InitializeComponent();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            // 获取摄像头列表
            int ErrorCode = MF_GetDeviceSources(out IntPtr devices, out int cch, true);
            if (ErrorCode >= 0)
            {
                string json = Marshal.PtrToStringUni(devices, cch);
                FreeMemory(devices);

                JArray Devices = JArray.Parse(json.Replace("\\", "\\\\"));
                ComboBoxCameraDevices.ItemsSource = Devices;
                ComboBoxCameraDevices.DisplayMemberPath = "Name"; // 显示成员路径
                ComboBoxCameraDevices.SelectedValuePath = "Moniker"; // 选择值成员路径
                ComboBoxCameraDevices.SelectedIndex = 0;
                if (Devices.Count == 1) ComboBoxCameraDevices.IsEnabled = false;                
            }
            else
            {   // 没有摄像头
                ButtonCaputre.IsEnabled = false;
            }

            // 获取 OPENCV_HOME 环境变量
            string OpenCvHome = Environment.GetEnvironmentVariable("OPENCV_HOME"); // OPENCV_HOME 由自己在环境变量中设置

            // 眼睛分类器
            EyeClassifier = new OpenCvSharp.CascadeClassifier(OpenCvHome + "\\sources\\data\\haarcascades\\haarcascade_eye.xml");

            // 人脸框分类器
            FaceClassifier = new OpenCvSharp.CascadeClassifier(OpenCvHome + "\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            CloseCapture();
        }

        private void CloseCapture()
        {
            ShouldStop = true; // 停止人脸检测
            WakeupResetEvent.Set(); // 停止等待下一帧
            if (Capture != null)
            {
                Capture.Release(); // 释放捕获设备
                Capture = null;
            }
        }

        private void ButtonCaputre_Click(object sender, RoutedEventArgs e)
        {
            if (IsRunning)
            {   // 关闭人脸检测
                CloseCapture();

                ButtonCaputre.Content = "开启摄像头";
                IsRunning = false;
            }
            else
            {   // 开启人脸检测
                Capture = OpenCvSharp.VideoCapture.FromCamera(ComboBoxCameraDevices.SelectedIndex);

                ShouldStop = false;
                WakeupResetEvent.Reset();
                if (ThreadPool.QueueUserWorkItem(new WaitCallback((state) => {
                    try
                    {
                        int millisecondsTimeout = (int)Math.Round(1000.0 / Capture.Fps); // 计算间隔
                        while (true)
                        {
                            if (ShouldStop) break; // 是否停止人脸检测

                            // 获取图像帧
                            OpenCvSharp.Mat Bgr = new OpenCvSharp.Mat();
                            if (Capture.Read(Bgr))
                            {
                                if (!Bgr.Empty())
                                {
                                    // 先进行灰度变换,然后通过直方图均衡化增加对比度          
                                    OpenCvSharp.Mat Gray = Bgr.CvtColor(OpenCvSharp.ColorConversionCodes.BGR2GRAY).EqualizeHist();

                                    // 检测眼睛位置
                                    OpenCvSharp.Rect[] Eyes = EyeClassifier.DetectMultiScale(Gray, 1.1, 2, (OpenCvSharp.HaarDetectionType)0, new OpenCvSharp.Size(30, 30));
                                    foreach (OpenCvSharp.Rect eye in Eyes) Bgr.Rectangle(eye, new OpenCvSharp.Scalar(0, 255, 0)); // 绿框标注

                                    // 检测人脸框位置
                                    OpenCvSharp.Rect[] Faces = FaceClassifier.DetectMultiScale(Gray, 1.1, 2, (OpenCvSharp.HaarDetectionType)0, new OpenCvSharp.Size(30, 30));
                                    foreach (OpenCvSharp.Rect face in Faces) Bgr.Rectangle(face, new OpenCvSharp.Scalar(0, 0, 255)); // 红框标注

                                    // 线程安全性
                                    this.Dispatcher.BeginInvoke(new Action(() => {
                                        ImageVideo.Source = Bgr.ToBitmapSource();
                                    }));
                                }
                            }

                            // 是否停止等待下一帧
                            if (WakeupResetEvent.WaitOne(millisecondsTimeout)) break;
                        }
                    }
                    catch
                    {
                        // 屏蔽异常
                    }
                })))
                {
                    ButtonCaputre.Content = "关闭摄像头";
                    IsRunning = true;
                }
                else
                {   // 启动人脸检测线程失败
                    ShouldStop = true;
                    WakeupResetEvent.Set();
                }
            }
        }

        // 基于单个图像的人脸检测
        private void ButtonSelect_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog
                {
                    Filter = "Image|*.jpg;*.bmp;*.png;*.tif;*.tga;*.ras;*.jp2;*.j2k;*.jpe",
                    DereferenceLinks = true
                };

                this.CenterChild();
                if (dlg.ShowDialog(Owner).Value == true)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback((state) => {
                        OpenCvSharp.Mat Bgr = OpenCvSharp.Cv2.ImRead(dlg.FileName); // 装载彩色图像
                        if (!Bgr.Empty())
                        {
                            // 先进行灰度变换,然后通过直方图均衡化增加对比度          
                            OpenCvSharp.Mat Gray = Bgr.CvtColor(OpenCvSharp.ColorConversionCodes.BGR2GRAY).EqualizeHist();

                            // 检测眼睛位置
                            OpenCvSharp.Rect[] Eyes = EyeClassifier.DetectMultiScale(Gray, 1.1, 2, (OpenCvSharp.HaarDetectionType)0, new OpenCvSharp.Size(30, 30));
                            foreach (OpenCvSharp.Rect eye in Eyes) Bgr.Rectangle(eye, new OpenCvSharp.Scalar(0, 255, 0)); // 绿框标注

                            // 检测人脸框位置
                            OpenCvSharp.Rect[] Faces = FaceClassifier.DetectMultiScale(Gray, 1.1, 2, (OpenCvSharp.HaarDetectionType)0, new OpenCvSharp.Size(30, 30));
                            foreach (OpenCvSharp.Rect face in Faces) Bgr.Rectangle(face, new OpenCvSharp.Scalar(0, 0, 255)); // 红框标注

                            // 线程安全性
                            this.Dispatcher.BeginInvoke(new Action(() => {
                                ImagePhoto.Source = Bgr.ToBitmapSource();
                            }));
                        }
                    }));
                }
            }
            catch (System.Exception exception)
            {
                MessageBoxPlus.Show(this, exception.Message, "图像文件异常", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void TabControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (((System.Windows.Controls.TabControl)sender).SelectedIndex == 1)
            {
                if (IsRunning) ButtonCaputre.RaiseEvent(new RoutedEventArgs(System.Windows.Controls.Button.ClickEvent));
            }
        }

        #region MF_AudioVideoDevices
        [DllImport("MF_AudioVideoDevices.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool Prepare();

        [DllImport("MF_AudioVideoDevices.dll")]
        public static extern int MF_GetDeviceSources(out IntPtr devices, out int cch, [MarshalAs(UnmanagedType.Bool)]bool video);

        [DllImport("MF_AudioVideoDevices.dll")]
        public static extern void FreeMemory(IntPtr p);
        #endregion        
    }
}

运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值