百度AI(5)人脸识别の人脸比对(C#)

同系列文章

源代码下载

BaiduAI.zip

演示程序界面

源代码
MainWindow.xaml.cs

/* ----------------------------------------------------------
 * 文件名称:MainWindow.xaml.cs
 * 
 * 作者:秦建辉
 * 
 * 微信:splashcn
 * 
 * 博客:http://www.firstsolver.com/wordpress/
 * 
 * 开发环境:
 *      Visual Studio V2017
 *      .NET Framework 4 Client Profile
 *      Baidu.AI 3.3.0.29135
 * 
 * 版本历史:
 *      V1.0	2018年01月18日
 *              百度AI 人脸比对演示示例
------------------------------------------------------------ */
using AForge.Video.DirectShow;
using Baidu.Aip.Face;
using Com.FirstSolver.CR;
using Com.FirstSolver.Splash;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Media.Imaging;

namespace FaceMatch
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        /// <summary>
        /// 核验通过
        /// </summary>
        private BitmapSource ImagePass;

        /// <summary>
        /// 核验失败
        /// </summary>
        private BitmapSource ImageDeny;

        private Face Client;
        private Dictionary<string, object> options = new Dictionary<string, object> {
            { "image_liveness", ",faceliveness"},   // 第一张图为证件照,不做活体检测;第二张图为视频照片,做活体检测
            { "types", "13,7"}
        };
        private byte[][] ImageCollection = new byte[2][]; // 锯齿数组

        /// <summary>
        /// 身份证读卡器
        /// </summary>
        private IDCardReader CardReader = null;

        /// <summary>
        /// 身份证读卡器同步事件
        /// </summary>
        private ManualResetEvent CardReaderSyncEvent = new ManualResetEvent(true);

        private volatile bool ShouldStop = true;
        private ManualResetEvent StartFaceMatchEvent = new ManualResetEvent(false);

        /// <summary>
        /// 人证比对通过阈值
        /// </summary>
        private double MatchThreshold = 70.0;

        /// <summary>
        /// 单帧活体阈值
        /// </summary>
        private double LivenessThreshold = 0.393241;

        public MainWindow()
        {
            InitializeComponent();

            // 核验通过图片
            ImagePass = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                Properties.Resources.pass.GetHbitmap(),
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());

            // 核验拒绝图片
            ImageDeny = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
                Properties.Resources.deny.GetHbitmap(),
                IntPtr.Zero,
                Int32Rect.Empty,
                BitmapSizeOptions.FromEmptyOptions());
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            InitializeMatch();

            // 初始化摄像头
            InitializeCamera();

            // 初始化读卡设备
            InitializeCardReader();
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            CloseMatch();
            CloseCamera();  // 关闭摄像头            
            CloseCardReader();  // 关闭读卡设备
        }

        private void InitializeMatch()
        {
            string API_KEY = "你的 Api Key";
            string SECRET_KEY = "你的 Secret Key";
            Client = new Face(API_KEY, SECRET_KEY);

            ThreadPool.QueueUserWorkItem(FaceMacthHandler);
        }

        private void CloseMatch()
        {
            ShouldStop = true;
            StartFaceMatchEvent.Set();
        }

        // 初始化摄像头
        private void InitializeCamera()
        {
            CloseCamera();  // 关闭摄像头

            // 设定初始视频设备
            FilterInfoCollection VideoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (VideoDevices.Count > 0)
            {
                VSP.VideoSource = new VideoCaptureDevice(VideoDevices[0].MonikerString);
                VSP.Start();
            }
            else
            {
                MessageBoxPlus.Show(this, "未发现摄像头!", "摄像头错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        // 关闭摄像头
        private void CloseCamera()
        {
            if (VSP.VideoSource != null && VSP.IsRunning)
            {   // 停止视频
                VSP.SignalToStop();
                VSP.WaitForStop();
            }
        }

        // 初始化读卡器
        private void InitializeCardReader()
        {
            CloseCardReader(); // 关闭读卡器

            try
            {
                CardReader = new YAReader() { ExternalSyncEvent = CardReaderSyncEvent };
                CardReader.OnReadCardCompleted += ReadCardCompletedHandler; // 事件处理器
                if (CardReader.Start(IDCardBiometrics.Photo) == -1)
                {
                    MessageBoxPlus.Show(this.Owner, "开启身份证扫描服务失败!", "读卡器错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            catch (Exception exception)
            {
                MessageBoxPlus.Show(this, exception.Message, "读卡器错误", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
        }

        // 停止身份证扫描服务
        private void CloseCardReader()
        {
            if (CardReader != null) { CardReader.Close(); CardReader = null; }
        }

        // 刷身份证处理器
        private void ReadCardCompletedHandler(object sender, ReadCardCompletedEventArgs e)
        {
            if (e == null || e.Photo == null) return;

            this.Dispatcher.BeginInvoke(new Action(() =>
            {   // 清除结果
                ImageVideo.Source = null;
                ImageAnswer.Source = null;
                TextBlockScore.Text = string.Empty;

                // 显示身份证信息
                TextBlockName.Text = e.Name;    // 姓名
                TextBlockGender.Text = e.Gender;    // 性别
                TextBlockNationality.Text = e.EthnicName;   // 民族
                TextBlockBirth.Text = e.Birth;  // 出生
                TextBlockSN.Text = e.IDC;   // 身份证号码
                TextBlockAddress.Text = e.Address;  // 地址

                ImageCollection[0] = e.Photo;
                this.Dispatcher.Invoke(new Action(() => {
                    ImagePhoto.Source = e.Photo.ToBitmapImage();
                }));

                ShouldStop = false;
                StartFaceMatchEvent.Set();
            }));
        }

        private void FaceMacthHandler(object state)
        {
            while (true)
            {
                StartFaceMatchEvent.WaitOne();
                if (ShouldStop) break;

                using (System.Drawing.Bitmap bmp = VSP.GetCurrentVideoFrame())
                {
                    ImageCollection[1] = bmp.ToByteArray();
                    var result = Client.Match(ImageCollection, options);
                    var error_code = result["error_code"];
                    if (error_code != null)
                    {
                        MessageBoxPlus.Show(this, result["error_msg"].ToString(), "错误", MessageBoxButton.OK, MessageBoxImage.Warning);
                        StartFaceMatchEvent.Reset();
                    }
                    else if ((int)result["result_num"] == 1)
                    {   // 验证活体
                        if (double.Parse(result["ext_info"]["faceliveness"].ToString().Split(new char[] { ',' })[1]) > LivenessThreshold)
                        {
                            foreach (dynamic item in result["result"])
                            {
                                this.Dispatcher.Invoke(new Action(() => {
                                    ImageVideo.Source = bmp.ToBitmapImage();

                                    double Score = (double)item["score"];
                                    ImageAnswer.Source = (Score >= MatchThreshold) ? ImagePass : ImageDeny;
                                    TextBlockScore.Text = Score.ToString();
                                }));

                                CardReaderSyncEvent.Set(); // 开启新的读卡信号
                                StartFaceMatchEvent.Reset(); // 等待新的人脸匹配信号
                            }
                        }
                    }
                }
            }
        }
    }
}

MainWindow.xaml

<Window x:Class="FaceMatch.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="clr-namespace:AForge.Controls;assembly=AForge.Controls"
        Title="百度AI 人脸比对演示示例" WindowStartupLocation="CenterScreen" FontSize="16" Icon="FR.ico" SizeToContent="WidthAndHeight" Loaded="Window_Loaded" Closing="Window_Closing">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="946"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <WindowsFormsHost Grid.Column="0" Margin="4" Width="730" Height="534">
            <controls:VideoSourcePlayer x:Name="VSP"/>
        </WindowsFormsHost>

        <Grid Grid.Column="1">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>

            <GroupBox Grid.Row="0" Margin="4">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>

                    <Border Grid.Row="0" Grid.Column="0" BorderThickness="1" Margin="4" BorderBrush="LightGray" Width="142" Height="166">
                        <Image Name="ImageVideo" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Border>

                    <Border Grid.Row="0" Grid.Column="1" BorderThickness="1" Margin="4" BorderBrush="LightGray" Width="142" Height="166">
                        <Image Name="ImagePhoto" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                    </Border>

                    <Label Content="实时照" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Foreground="#666666"/>
                    <Label Content="证件照" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Foreground="#666666"/>
                </Grid>
            </GroupBox>

            <GroupBox Grid.Row="1" Margin="4">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition/>
                        <RowDefinition/>
                    </Grid.RowDefinitions>

                    <Image Name="ImageAnswer" Grid.Row="0" Width="128" Height="128"/>

                    <Grid Grid.Row="1">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>

                        <Label Grid.Column="0" Content="相似度:" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontSize="22" Foreground="#333333"/>
                        <TextBlock Name="TextBlockScore" Grid.Column="1" VerticalAlignment="Center" FontSize="22" Foreground="#333333"/>
                    </Grid>
                </Grid>
            </GroupBox>

            <GroupBox Grid.Row="2" Margin="4">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>

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

                    <Label Grid.Row="0" Grid.Column="0" Content="姓名" Foreground="#555555"/>
                    <Label Grid.Row="0" Grid.Column="2" Content="性别" Foreground="#555555"/>
                    <Label Grid.Row="1" Grid.Column="0" Content="民族" Foreground="#555555"/>
                    <Label Grid.Row="1" Grid.Column="2" Content="出生" Foreground="#555555"/>
                    <Label Grid.Row="2" Grid.Column="0" Content="证件号" Foreground="#555555"/>
                    <Label Grid.Row="3" Grid.Column="0" Content="地址" Foreground="#555555"/>

                    <TextBlock Name="TextBlockName" Grid.Row="0" Grid.Column="1" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="#777777"/>
                    <TextBlock Name="TextBlockGender" Grid.Row="0" Grid.Column="3" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="#777777"/>
                    <TextBlock Name="TextBlockNationality" Grid.Row="1" Grid.Column="1" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="#777777"/>
                    <TextBlock Name="TextBlockBirth" Grid.Row="1" Grid.Column="3" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="#777777"/>
                    <TextBlock Name="TextBlockSN" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="3" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="#777777"/>
                    <TextBlock Name="TextBlockAddress" Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="3" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="#777777"/>
                </Grid>
            </GroupBox>
        </Grid>
    </Grid>
</Window>

Comments are closed.