C# 对接第三方平台AI功能实现人脸识别

准备工作

引入华为云人脸识别模块SDK

在项目中引入 Aforge

  • 选择项目右键>管理NuGet程序包>搜索Aforge>安装下面六个组件
    >AForge
    >AForge.Imaging
    >AForge.Math
    >AForge.Video
    >AForge.Video.DirectShow
    >AForge.Video.Control
    引入 Aforge

在项目中引入 Newtonsoft.Json

  • 选择项目右键>管理NuGet程序包>搜索Newtonsoft.Json>安装Newtonsoft.Json
    引入 Newtonsoft.Json

前期准备工作完成,开工

1. 窗体设计

人脸检测窗体设计
  • 控件信息
控件类型 控件名称 控件描述
VideoSourcePlayer vispShoot 视频控件,用于显示摄像头拍摄信息
Button btnDetect 拍照检测按钮
Button btnStart 开始自动检测按钮
Button btnDetect 结束自动检测按钮
Timer timeShoot 自动检测定时器,用于定时拍照检测
PictureBox pbFaceImage 拍照图片展示图形框,用于展示拍照得到的图像
TextBox TextBox 文本框,用于展示人脸检测结果
  • 附设计自动生成代码
namespace huaweiCloudDemo
{
    partial class 人脸检测
    {
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows 窗体设计器生成的代码

        /// <summary>
        /// 设计器支持所需的方法 - 不要修改
        /// 使用代码编辑器修改此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.vispShoot = new AForge.Controls.VideoSourcePlayer();
            this.btnDetect = new System.Windows.Forms.Button();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.label2 = new System.Windows.Forms.Label();
            this.label1 = new System.Windows.Forms.Label();
            this.pbFaceImage = new System.Windows.Forms.PictureBox();
            this.lblResult = new System.Windows.Forms.Label();
            this.btnStart = new System.Windows.Forms.Button();
            this.btnStop = new System.Windows.Forms.Button();
            this.timeShoot = new System.Windows.Forms.Timer(this.components);
            this.txtResult = new System.Windows.Forms.TextBox();
            this.groupBox1.SuspendLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pbFaceImage)).BeginInit();
            this.SuspendLayout();
            // 
            // vispShoot
            // 
            this.vispShoot.Location = new System.Drawing.Point(64, 37);
            this.vispShoot.Name = "vispShoot";
            this.vispShoot.Size = new System.Drawing.Size(527, 447);
            this.vispShoot.TabIndex = 0;
            this.vispShoot.Text = "videoSourcePlayer1";
            this.vispShoot.VideoSource = null;
            // 
            // btnDetect
            // 
            this.btnDetect.Font = new System.Drawing.Font("宋体", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnDetect.Location = new System.Drawing.Point(234, 523);
            this.btnDetect.Name = "btnDetect";
            this.btnDetect.Size = new System.Drawing.Size(184, 63);
            this.btnDetect.TabIndex = 1;
            this.btnDetect.Text = "拍照检测";
            this.btnDetect.UseVisualStyleBackColor = true;
            this.btnDetect.Click += new System.EventHandler(this.btnCheck_Click);
            // 
            // groupBox1
            // 
            this.groupBox1.Controls.Add(this.txtResult);
            this.groupBox1.Controls.Add(this.lblResult);
            this.groupBox1.Controls.Add(this.label2);
            this.groupBox1.Controls.Add(this.label1);
            this.groupBox1.Controls.Add(this.pbFaceImage);
            this.groupBox1.Font = new System.Drawing.Font("宋体", 15F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.groupBox1.Location = new System.Drawing.Point(666, 37);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(554, 809);
            this.groupBox1.TabIndex = 2;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "检测结果";
            // 
            // label2
            // 
            this.label2.AutoSize = true;
            this.label2.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label2.Location = new System.Drawing.Point(25, 327);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(130, 24);
            this.label2.TabIndex = 2;
            this.label2.Text = "检测结果:";
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.label1.Location = new System.Drawing.Point(25, 156);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(130, 24);
            this.label1.TabIndex = 1;
            this.label1.Text = "检测图片:";
            // 
            // pbFaceImage
            // 
            this.pbFaceImage.Location = new System.Drawing.Point(161, 41);
            this.pbFaceImage.Name = "pbFaceImage";
            this.pbFaceImage.Size = new System.Drawing.Size(356, 273);
            this.pbFaceImage.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
            this.pbFaceImage.TabIndex = 0;
            this.pbFaceImage.TabStop = false;
            // 
            // lblResult
            // 
            this.lblResult.AutoSize = true;
            this.lblResult.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.lblResult.Location = new System.Drawing.Point(49, 391);
            this.lblResult.Name = "lblResult";
            this.lblResult.Size = new System.Drawing.Size(0, 24);
            this.lblResult.TabIndex = 5;
            // 
            // btnStart
            // 
            this.btnStart.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnStart.Location = new System.Drawing.Point(64, 627);
            this.btnStart.Name = "btnStart";
            this.btnStart.Size = new System.Drawing.Size(184, 63);
            this.btnStart.TabIndex = 3;
            this.btnStart.Text = "开始自动检测";
            this.btnStart.UseVisualStyleBackColor = true;
            this.btnStart.Click += new System.EventHandler(this.btnStart_Click);
            // 
            // btnStop
            // 
            this.btnStop.Font = new System.Drawing.Font("宋体", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.btnStop.Location = new System.Drawing.Point(407, 627);
            this.btnStop.Name = "btnStop";
            this.btnStop.Size = new System.Drawing.Size(184, 63);
            this.btnStop.TabIndex = 4;
            this.btnStop.Text = "结束自动检测";
            this.btnStop.UseVisualStyleBackColor = true;
            this.btnStop.Click += new System.EventHandler(this.btnStop_Click);
            // 
            // timeShoot
            // 
            this.timeShoot.Interval = 1000;
            this.timeShoot.Tick += new System.EventHandler(this.timeShoot_Tick);
            // 
            // txtResult
            // 
            this.txtResult.Font = new System.Drawing.Font("宋体", 10.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
            this.txtResult.Location = new System.Drawing.Point(29, 381);
            this.txtResult.Multiline = true;
            this.txtResult.Name = "txtResult";
            this.txtResult.ScrollBars = System.Windows.Forms.ScrollBars.Both;
            this.txtResult.Size = new System.Drawing.Size(488, 396);
            this.txtResult.TabIndex = 6;
            // 
            // 人脸检测
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(1273, 885);
            this.Controls.Add(this.btnStop);
            this.Controls.Add(this.btnStart);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.btnDetect);
            this.Controls.Add(this.vispShoot);
            this.Name = "人脸检测";
            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
            this.Text = "人脸检测";
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.人脸检测_FormClosing);
            this.Load += new System.EventHandler(this.人脸检测_Load);
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            ((System.ComponentModel.ISupportInitialize)(this.pbFaceImage)).EndInit();
            this.ResumeLayout(false);

        }

        #endregion

        private AForge.Controls.VideoSourcePlayer vispShoot;
        private System.Windows.Forms.Button btnDetect;
        private System.Windows.Forms.GroupBox groupBox1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.PictureBox pbFaceImage;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.Label lblResult;
        private System.Windows.Forms.Button btnStart;
        private System.Windows.Forms.Button btnStop;
        private System.Windows.Forms.Timer timeShoot;
        private System.Windows.Forms.TextBox txtResult;
    }
}


2. FaceUtil(华为云人脸识别SDK工具类 )

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AForge.Imaging;

//引入华为云SDK命名空间
using FrsSDK.client;
using FrsSDK.client.param;
using FrsSDK.client.result;

namespace huaweiCloudDemo.utils
{
    /// <summary>
    /// 华为云(https://support.huaweicloud.com/sdkreference-face/face_04_0018.html)
    /// 人脸操作工具类
    /// </summary>
    class FaceUtil
    {
        //华为AK/SK/projectId 可在“我的凭证”界面获取(https://console.huaweicloud.com/iam/?locale=zh-cn#/myCredential)
        //Access Key Id
        private const string ak = "***";
        //Secret Access Key
        private const string sk = "***";
        //项目id 可在
        private const string projectId = "***";
        //图片存储本地地址
        private const string imageLocalUrl = "D:\\resources\\image\\faces";


        /// <summary>
        /// 人脸检测
        /// 具体传入参数,返回参数请参考(https://support.huaweicloud.com/api-face/face_02_0052.html)
        /// </summary>
        /// <param name="image">图片地址(本地图片)</param>
        /// /// <param name="attributes">人脸属性,默认无,多个逗号(,)隔开(0:人脸姿态,1:性别,2:年龄,3:人脸关键点,4:装束(帽子,眼镜)5:笑脸)</param>
        /// <returns>检测结果(JSON格式字符串)</returns>
        public static DetectFaceResult DetectFaceByFile(Bitmap image, string attributes = null)
        {
            AuthInfo authInfo = new AuthInfo("https://face.cn-north-1.myhuaweicloud.com", ak, sk);
            FrsClient frsClient = new FrsClient(authInfo, projectId);
            DetectFaceResult detectFaceResult = frsClient.GetDetectService().DetectFaceByFile(SaveImageToLoacl(image), attributes);
            return detectFaceResult;
        }




        /// <summary>
        /// 图片本地存储
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        public static string SaveImageToLoacl(Bitmap image)
        {
            //判断图片本地存储文件夹是否存在,不存在则创建
            if (!Directory.Exists(imageLocalUrl))
            {
                Directory.CreateDirectory(imageLocalUrl);
            }
            string dateStr = DateTime.Now.ToString("yyyyMMdd");
            //图片文件按天生成文件夹
            if (!Directory.Exists(imageLocalUrl + "\\" + dateStr))
            {
                Directory.CreateDirectory(imageLocalUrl + "\\" + dateStr);
            }
            string dateTimeStr = DateTime.Now.ToString("yyyyMMddhhmmssfff");
            string imageUrl = imageLocalUrl + "\\" + dateStr + "\\" + dateTimeStr + ".jpeg";
            image.Save(imageUrl, System.Drawing.Imaging.ImageFormat.Jpeg);
            return imageUrl;
        }
    }
}

3. 窗体控件操作代码

using AForge.Video.DirectShow;
using FrsSDK.client.result;
using FrsSDK.client.result.common;
using huaweiCloudDemo.utils;
using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace huaweiCloudDemo
{
    public partial class 人脸检测 : Form
    {
        public 人脸检测()
        {
            InitializeComponent();
        }


        private void btnCheck_Click(object sender, EventArgs e)
        {
            //拍照获得图片
            Bitmap img = vispShoot.GetCurrentVideoFrame();
            //展示图片
            this.pbFaceImage.Image = img;
            txtResult.Text = "";
            DetectFaceResult result = FaceUtil.DetectFaceByFile(img,"1,2,5");
            StringBuilder sb = new StringBuilder();
            if (result.faces.Count > 0)
            {
                sb.AppendFormat("人脸数量:{0}\r\n", result.faces.Count);
                for (int i = 0; i < result.faces.Count; i++)
                {
                    DetectFace df = result.faces[i];
                    if (df.attributes != null)
                    {
                        sb.AppendFormat("-----第{0}张脸-----\r\n", i + 1);
                        sb.AppendFormat("年龄:{0}\r\n", df.attributes.age);
                        string gender = "";
                        if (df.attributes.gender == "male")
                        {
                            gender = "男";
                        }
                        else if (df.attributes.gender == "female")
                        {
                            gender = "女";
                        }
                        else
                        {

                        }
                        sb.AppendFormat("性别:{0}\r\n", gender);
                        sb.AppendFormat("笑脸:{0}\r\n", df.attributes.smile);
                    }

                    txtResult.Text = sb.ToString();
                }
            }
            else
            {
                txtResult.Text = "未检测到人脸\r\n";
            } 
        }

        /// <summary>
        /// 窗体加载
        /// 初始化打开摄像头
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 人脸检测_Load(object sender, EventArgs e)
        {
            initVideo();
        }

        private FilterInfoCollection videoDevices;
        private VideoCaptureDevice videoDevice;
        private VideoCapabilities[] videoCapabilities;
        /// <summary>
        /// 初始化摄像头
        /// </summary>
        public void initVideo()
        {
            videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
            if (videoDevices.Count != 0)
            {
                //foreach (FilterInfo device in videoDevices)
                //{
                //    MessageBox.Show(device.Name);
                //}
                //默认取识别到的第一个摄像头
                //如有需要可选择摄像头加载
                videoDevice = new VideoCaptureDevice(videoDevices[0].MonikerString);
                videoCapabilities = videoDevice.VideoCapabilities;
                videoDevice.VideoResolution = videoCapabilities[0];
                //加载到视频控件
                vispShoot.VideoSource = videoDevice;
                vispShoot.Start();
            }
            else
            {
                MessageBox.Show("没有找到摄像头");
            }
        }

        /// <summary>
        /// 关闭摄像头
        /// </summary>
        private void DisConnect()
        {
            if (vispShoot.VideoSource != null)
            {
                vispShoot.SignalToStop();
                vispShoot.WaitForStop();
                vispShoot.VideoSource = null;
            }
        }

        /// <summary>
        /// 窗体关闭监听事件
        /// 当前窗体关闭时执行关闭摄像头方法,不然摄像头会一直开着
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 人脸检测_FormClosing(object sender, FormClosingEventArgs e)
        {
            DisConnect();
        }

        public int stootCount = 1;

        /// <summary>
        /// 定时器 定时执行事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timeShoot_Tick(object sender, EventArgs e)
        {
            //拍照获得图片
            Bitmap img = vispShoot.GetCurrentVideoFrame();
            //展示图片
            this.pbFaceImage.Image = img;
           
            DetectFaceResult result = FaceUtil.DetectFaceByFile(img, "1,2,5");
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("------------第({0})次自动检测-------------\r\n", stootCount);
            if (result.faces.Count > 0)
            {
                sb.AppendFormat("人脸数量:{0}\r\n", result.faces.Count);
                for (int i = 0; i < result.faces.Count; i++)
                {
                    DetectFace df = result.faces[i];
                    if (df.attributes != null)
                    {
                        sb.AppendFormat("-----第{0}张脸-----\r\n", i + 1);
                        sb.AppendFormat("年龄:{0}\r\n", df.attributes.age);
                        string gender = "";
                        if (df.attributes.gender == "male")
                        {
                            gender = "男";
                        }
                        else if (df.attributes.gender == "female")
                        {
                            gender = "女";
                        }
                        else
                        {
                            gender = "无法判断";
                        }
                        sb.AppendFormat("性别:{0}\r\n", gender);
                        sb.AppendFormat("笑脸:{0}\r\n", df.attributes.smile);
                    }

                    
                }
            }
            else
            {
                sb.AppendFormat("未检测到人脸\r\n");
            }
            txtResult.Text += sb.ToString();
            stootCount++;
        }

        /// <summary>
        /// 开始自动检测按钮点击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            txtResult.Text = "";
            timeShoot.Start();
        }

        /// <summary>
        /// 关闭自动检测按钮点击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStop_Click(object sender, EventArgs e)
        {
            timeShoot.Stop();
        }
    }
}

5. 运行效果(AI还不够聪明,年龄检测结果大了太多o(╥﹏╥)o)

运行效果o(╥﹏╥)o

6. 完整demo下载地址

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,192评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,858评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,517评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,148评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,162评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,905评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,537评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,439评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,956评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,083评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,218评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,899评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,565评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,093评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,201评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,539评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,215评论 2 358