简单的人脸识别

#最近实践周做了个活体检测和人脸识别
##1.1 目的
人脸识别系统以人脸识别技术为核心,是一项新兴的生物识别技术,是当今国际科技领域攻关的高精尖技术。它广泛采用区域特征分析算法,融合了计算机图像处理技术与生物统计学原理于一体,利用计算机图像处理技术从视频中提取人像特征点,利用生物统计学的原理进行分析建立数学模型,具有广阔的发展前景。在本次设计过程中我们详细的了解了人脸识别中活体检测的内容和应用。

##2. 运用及功能
2.1人脸识别技术与应用
人脸识别,是通过采集人脸图像,获取其脸部特征信息后,利用匹配识别技术与数
据库中的人脸数据信息匹配比较,从而实现识别身份的生物特征识别技术[14]。先通过摄像机等设备获取人脸图像,再输入到计算机、数字信号处理、嵌入式等计算分析平台,接着利用数字图像处理技术进行图像预处理,利用人脸检测算法检测图像中是否有人脸的存在,如有,则进行特征提取,最后匹配识别等一系列相关技术的处理。因此,人脸识别系统主要由五部分组成:图像采集,人脸检测、图像预处理、人脸特征提取以及匹配识别。

2.2.2功能实现

这里是引用
使用百度AI开放平台,它免费开放一定并发量的该场景活体检测 API:
https://ai.baidu.com/tech/face/faceliveness
第一步,申请百度应用
点击“立即使用”,登录后“创建应用”,可以得到 API Key 与 Secret Key 等信息。
第二步,使用 API 进行活体检测
这里的场景比较简单,摄像头获取的影像可以保存为图片,则功能接口可以这样定义:给定图片(这里使用URL),判断其活体影像的概率。根据百度建议,概率设置为 99.5%,即达到此值或以上认为活体检测通过。
(1)获取 accessToken
accessToken 有效期为 30 天,因此,可以缓存起来使用。此为示例,时长又足够长,所以未加刷新机制。代码如下,其中,clientId 为百度应用中的 API Key,clientSecret 为百度应用中的 Secret Key。
public static class AccessToken
{
// 有效期30天,缓存获取的 access token
public static String TOKEN = null;
// 百度云中开通对应服务应用的 API Key
private static String clientId = “API Key”;
// 百度云中开通对应服务应用的 Secret Key
private static String clientSecret = “Secret Key”;
public static String getAccessToken()
{
if (String.IsNullOrEmpty(TOKEN))
{
String authHost = “https://aip.baidubce.com/oauth/2.0/token”;
HttpClient client = new HttpClient();
List<KeyValuePair<String, String>> paraList = new List<KeyValuePair<string, string>>();
paraList.Add(new KeyValuePair<string, string>(“grant_type”, “client_credentials”));
paraList.Add(new KeyValuePair<string, string>(“client_id”, clientId));
paraList.Add(new KeyValuePair<string, string>(“client_secret”, clientSecret));
HttpResponseMessage response = client.PostAsync(authHost, new FormUrlEncodedContent(paraList)).Result;
String result = response.Content.ReadAsStringAsync().Result;
JObject jr = JObject.Parse(result);
TOKEN = jr.Value(“access_token”);
}
return TOKEN;
}
}
(2)调用 API 取得活体概率
API 的返回结果为 JSON,其中包括了活体概率,这里,方法直接返回 API 的 JSON 结果。
public class FaceLivenessHelper
{
// 在线活体检测
public static string FaceVerify(string imgUrl)
{
string token = AccessToken.getAccessToken();
string host = “https://aip.baidubce.com/rest/2.0/face/v3/faceverify?access_token=” + token;
Encoding encoding = Encoding.Default;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
request.Method = “post”;
request.KeepAlive = true;
// String str = “[{“image”:“sfasq35sadvsvqwr5q…”,“image_type”:“BASE64”,“face_field”:“age,beauty,expression”}]”;
String str = “[{“image”:”" + imgUrl + “”,“image_type”:“URL”,“face_field”:“age,beauty,expression”}]";
byte[] buffer = encoding.GetBytes(str);
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
string result = reader.ReadToEnd();
Console.WriteLine(“在线活体检测:”);
Console.WriteLine(result);
return result;
}
}
详细 API 文档见此:https://ai.baidu.com/docs#/Face-Liveness-V3/top
结果中:face_liveness 即表示“活体分数值”。
(3)应用
API 的调用结果中,error_code 为 0 时表示执行成功,此时,会有 result 属性表示计算的相关值,从中取出 face_liveness 即可,其值为 0 ~ 1之间。
string imgUrl = “------”;
string result = FaceLivenessHelper.FaceVerify(imgUrl);
JObject jresult = JObject.Parse(result);
JObject lvresult = jresult.Value(“result”);
// error_code 为 0 时表示执行成功,其它表示失败
if (jresult.Value(“error_code”) == 0)
{
double face_liveness = lvresult.Value(“face_liveness”);
// 活体率达到要求
if (face_liveness >= 0.995)
{
// 通过检测
}
(4)活体阈值参考
检测的图片为二次采集,即通过相机当场拍摄,确保时间及操作条件的约束;
SDK输出的多帧情况,只要这些帧中,任何一张通过了阈值,即可判断为活体,建议可用三帧情况;
推荐分值采用99.5%
关于活体检测faceliveness的判断阈值选择,可参考以下数值信息:
拒绝率(TRR) 误拒率(FRR) 通过率(TAR) 阈值(Threshold)
0.90325733 0.1% 99.9% 0.022403
0.96254072 0.5% 99.5% 0.393241(推荐)
0.97557003 1% 99% 0.649192
0.98990228 2% 98% 0.933801
0.99446254 3% 97% 0.973637
0.99641694 4% 96% 0.988479
0.99739414 5% 95% 0.994058
关于以上数值的概念介绍:
拒绝率(TRR):如99%,代表100次作弊假体攻击,会有99次被拒绝。
误拒率(FRR):如0.5%,指1000次真人请求,会有5次因为活体分数低于阈值被错误拒绝。
通过率(TAR):如99%,指100次真人请求,会有99次因为活体分数高于阈值而通过。
阈值(Threshold):高于此数值,则可判断为活体。
质量检测参考
指标 字段与解释 推荐数值界限
遮挡范围 occlusion,取值范围[0~1],0为无遮挡,1是完全遮挡
含有多个具体子字段,表示脸部多个部位
通常用作判断头发、墨镜、口罩等遮挡 left_eye : 0.6, #左眼被遮挡的阈值
right_eye : 0.6, #右眼被遮挡的阈值
nose : 0.7, #鼻子被遮挡的阈值
mouth : 0.7, #嘴巴被遮挡的阈值
left_check : 0.8, #左脸颊被遮挡的阈值
right_check : 0.8, #右脸颊被遮挡的阈值
chin_contour : 0.6, #下巴被遮挡阈值
模糊度范围 blur,取值范围[0~1],0是最清晰,1是最模糊 小于0.7
光照范围 illumination,取值范围[0~255]
脸部光照的灰度值,0表示光照不好
以及对应客户端SDK中,YUV的Y分量 大于40
姿态角度 Pitch:三维旋转之俯仰角度[-90(上), 90(下)]
Roll:平面内旋转角[-180(逆时针), 180(顺时针)]
Yaw:三维旋转之左右旋转角[-90(左), 90(右)] 分别小于20度
人脸完整度 completeness(0或1),0为人脸溢出图像边界,1为人脸都在图像边界内 视业务逻辑判断
人脸大小 人脸部分的大小
建议长宽像素值范围:8080~200200 人脸部分不小于100*100像素
人脸空间姿态角参考
姿态角分为Pitch、Roll、Yaw,用于表示人脸在空间三维坐标系内的角度,常用于判断识别角度的界限值。
各角度阈值如下:
Pitch:三维旋转之俯仰角度,范围:[-90(上), 90(下)],推荐俯仰角绝对值不大于20度;
Roll:平面内旋转角,范围:[-180(逆时针), 180(顺时针)],推荐旋转角绝对值不大于20度;
Yaw:三维旋转之左右旋转角,范围:[-90(左), 90(右)],推荐旋转角绝对值不大于20度;
各角度范围示意图如下:
从姿态角度来看,这三个值的绝对值越小越好,这样代表人脸足够正视前方,最利于实际注册/识别使用。

##程序代码
在这里插入图片描述

namespace FaceCheck
{
    public partial class Form1 : Form
    {
       //static bool index = false;//用作切换图片的标志,false切换到线下图片,true切换到线上图片
        /// <summary>
        /// 图片转换为Base64
        /// </summary>
        /// <param name="image"></param>
        /// <returns></returns>
        private string ImgToBase64String(string image)
        {
            try
            {
                Bitmap bmp = new Bitmap(image, true);
                MemoryStream ms = new MemoryStream();
                bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                byte[] arr = new byte[ms.Length];
                ms.Position = 0;
                ms.Read(arr, 0, (int)ms.Length);
                ms.Close();

                return Convert.ToBase64String(arr);
            }
            catch (Exception)
            {
                return null;
            }
        }
        // 在线活体检测
        public static string FaceVerify(string imgUrl)
        {
            string token = AccessToken.getAccessToken();
            string host = "https://aip.baidubce.com/rest/2.0/face/v3/faceverify?access_token=" + token;
            Encoding encoding = Encoding.Default;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(host);
            request.Method = "post";
            request.KeepAlive = true;       
                ///<summary>
                ///图片换为BASE64格式
                /// </summary>
                String str = "[{\"image\":\"" + imgUrl + "\",\"image_type\":\"BASE64\",\"face_field\":\"age,beauty,expression\"}]";
          
                ///<summary>
                ///图片换为URL统一资源定位符
                /// </summary>
               // String str = "[{\"image\":\"" + imgUrl + "\",\"image_type\":\"URL\",\"face_field\":\"age,beauty,expression\"}]";
                byte[] buffer = encoding.GetBytes(str);
                request.ContentLength = buffer.Length;
                request.GetRequestStream().Write(buffer, 0, buffer.Length);
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default);
      
               string result = reader.ReadToEnd();
               Console.WriteLine("在线活体检测:");
               Console.WriteLine(result);
               return result;
            //百度示例
            // String str =  "[{\"image\":\"sfasq35sadvsvqwr5q...\",\"image_type\":\"BASE64\",\"face_field\":\"age,beauty,expression\"},{\"image\":\"http://xxx.baidu.com/image1.png\",\"image_type\":\"URL\",\"face_field\":\"age,beauty\"}]";
        }
        public Form1()
        {
            InitializeComponent();
            
        }
        private void button2_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                //PictureBox控件显示图片
                pictureBox1.Load(openFileDialog1.FileName);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (radioButton_local.Checked)
            {
               
                string imgUrl = ImgToBase64String(openFileDialog1.FileName.ToString());
                string result = FaceVerify(imgUrl);
                JObject jresult = JObject.Parse(result);
                JObject lvresult = jresult.Value<JObject>("result");
               // JObject flresult = jresult.Value<JObject>("face_list");
                // error_code 为 0 时表示执行成功,其它表示失败
                if (jresult.Value<int>("error_code") == 0)
                {
                    double face_liveness = lvresult.Value<double>("face_liveness");
                    string face_livenessx = lvresult.Value<string>("face_liveness");
                   // string age = lvresult.Value<string>("face_list".Contains("age"));
                    // double age = lvresult.Value<double>("age");
                    //string beauty = lvresult.Value<string>("face_list");
                    face_livenesstest.Text = "活体分数值:" + face_livenessx;
                   // agetest.Text = "年龄:"+age.Tostring();
                   // beautytest.Text = "美丑打分:"+beauty;
                    richTextBox2.Text = jresult.ToString();
                    // 活体率达到要求
                    if (face_liveness >= 0.995)
                    {
                        // 通过检测
                        label1.Text = "通过!!!";
                    }
                    else
                        label1.Text = "不通过!!!";
                }
            }
            if (radioButton_online.Checked)
            {
               
                //string imgUrl = "http://photocdn.sohu.com/20110926/Img320590872.jpg";
                string imgUrl = textBox1.Text;
                string result = FaceVerify(imgUrl);
                JObject jresult = JObject.Parse(result);
                JObject lvresult = jresult.Value<JObject>("result");
                // error_code 为 0 时表示执行成功,其它表示失败
                if (jresult.Value<int>("error_code") == 0)
                {
                    double face_liveness = lvresult.Value<double>("face_liveness");
                    string face_livenessx = lvresult.Value<string>("face_liveness");
                 
                    face_livenesstest.Text = face_livenessx;
                 
                    richTextBox2.Text = jresult.ToString();
                    // 活体率达到要求
                    if (face_liveness >= 0.995)
                    {
                        // 通过检测
                        label1.Text = "通过!!!";
                    }
                    else
                        label1.Text = "不通过!!!";
                }
            }
      
        }

        private void richTextBox2_TextChanged(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 质量检测(可选)活体检测(可选)公安验证(必选)
        /// </summary>
        //    public void PersonVerifyDemo()
        //    {
        //        var image = "取决于image_type参数,传入BASE64字符串或URL字符串或FACE_TOKEN字符串";

        //        var imageType = "BASE64";

        //        var idCardNumber = "110233112299822211";

        //        var name = "张三";

        //        // 调用身份验证,可能会抛出网络等异常,请使用try/catch捕获
        //        var result = client.PersonVerify(image, imageType, idCardNumber, name);
        //        Console.WriteLine(result);
        //        // 如果有可选参数
        //        var options = new Dictionary<string, object>{
        //    {"quality_control", "NORMAL"},
        //    {"liveness_control", "LOW"}
        //    };
        //        // 带参数调用身份验证
        //        result = client.PersonVerify(image, imageType, idCardNumber, name, options);
        //        Console.WriteLine(result);
        //    }

        //    public string ReadImg(string img)
        //    {
        //        return Convert.ToBase64String(File.ReadAllBytes(img));
        //    }
        //    /// <summary>
        //    /// 人脸基础信息,人脸质量检测,基于图片的活体检测
        //    /// </summary>
        //    public void Demo()
        //    {
        //        var faces = new JArray
        //{
        //    new JObject
        //    {
        //        {"image", ReadImg("/ym1.jpeg")},
        //        {"image_type", "BASE64"},
        //        {"face_field", "age,beauty"},
        //    },
        //    new JObject
        //    {
        //        {"image", ReadImg("/ym2.jpeg")},
        //        {"image_type", "BASE64"}
        //    }
        //};
        //        var result = client.Faceverify(faces);
        //        Console.WriteLine(result);
        //    }
    }
}

后期再放个成效的视频

全片(高清)

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
大学生参加学科竞赛有着诸多好处,不仅有助于个人综合素质的提升,还能为未来职业发展奠定良好基础。以下是一些分析: 首先,学科竞赛是提高专业知识和技能水平的有效途径。通过参与竞赛,学生不仅能够深入学习相关专业知识,还能够接触到最新的科研成果和技术发展趋势。这有助于拓展学生的学科视野,使其对专业领域有更深刻的理解。在竞赛过程中,学生通常需要解决实际问题,这锻炼了他们独立思考和解决问题的能力。 其次,学科竞赛培养了学生的团队合作精神。许多竞赛项目需要团队协作来完成,这促使学生学会有效地与他人合作、协调分工。在团队合作中,学生们能够学到如何有效沟通、共同制定目标和分工合作,这对于日后进入职场具有重要意义。 此外,学科竞赛是提高学生综合能力的一种途径。竞赛项目通常会涉及到理论知识、实际操作和创新思维等多个方面,要求参赛者具备全面的素质。在竞赛过程中,学生不仅需要展现自己的专业知识,还需要具备创新意识和解决问题的能力。这种全面的综合能力培养对于未来从事各类职业都具有积极作用。 此外,学科竞赛可以为学生提供展示自我、树立信心的机会。通过比赛的舞台,学生有机会展现自己在专业领域的优势,得到他人的认可和赞誉。这对于培养学生的自信心和自我价值感非常重要,有助于他们更加积极主动地投入学习和未来的职业生涯。 最后,学科竞赛对于个人职业发展具有积极的助推作用。在竞赛中脱颖而出的学生通常能够引起企业、研究机构等用人单位的关注。获得竞赛奖项不仅可以作为个人履历的亮点,还可以为进入理想的工作岗位提供有力的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值