一、实验目的
在Windows Forms应用程序中与百度的人脸识别API进行交互,实现人脸检测(检测年龄、颜值等),人脸比对(判断两张人脸图像的相似度)两个功能。
二、实验内容
1、窗体设计
该实验在Windows窗体应用中实现,需要拖动的相关控件如下:
2、代码设计
为了能够顺利调用百度AI,在代码中需要定义三个私有字符串变量,分别存储了应用程序ID、API密钥和秘钥,这些都是与百度AI服务交互时需要的认证信息。
private string APP_ID = "33711276";
private string API_KEY = "1nhS4AcrLFffxqDKB73bb1U7";
private string SECRET_KEY = "rtnRFv5RcE0dMxBWqmL6PX3LYwVAdETW";
定义一个私有变量client,它是Face类型,是百度AI SDK中的一个类,并初始化为null。这个变量将用于与百度的人脸识别服务进行通信。
private Face client = null;
定义两个私有变量:一个布尔类型的IsStart,用于表示是否可以开始人脸检测,和一个FaceLocation类型的location,用于存储人脸在图像中的位置信息。
private bool IsStart = false;
private FaceLocation location = null;
在Form1类的构造函数中,需使用之前定义的API密钥和秘钥创建一个Face客户端实例。
client = new Face(API_KEY, SECRET_KEY);
根据BaiduAI的要求,请求的图片需要经过Base64编码,下面将传入的图像转换为Base64编码的字符串并返回。
public string ConvertImageToBase64(Image file)
{
using (MemoryStream memoryStream = new MemoryStream())
{
file.Save(memoryStream, file.RawFormat);
byte[] imageBytes = memoryStream.ToArray();
return Convert.ToBase64String(imageBytes);
}
}
在实现人脸检测功能时,需要定义两个可选参数字典,用于与百度的人脸识别API交互,并调用client的Detect方法。
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = "E:\\教学\\VS222302 - desktop\\baiduAIFaceIdentify-master\\baiduAIFaceIdentify-master\\BaiduAI\\BaiduAI\\bin\\Debug";
dialog.Filter = "所有文件|*.*";
dialog.RestoreDirectory = true;
dialog.FilterIndex = 1;
if (dialog.ShowDialog() == DialogResult.OK)
{
string filename = dialog.FileName;
try
{
Image im = Image.FromFile(filename);
var image = ConvertImageToBase64(im);
string imageType = "BASE64";
// 如果有可选参数
var options = new Dictionary<string, object>{
//{"max_face_num", 2},
{"face_field", "age,beauty"},
{"face_fields", "age,qualities,beauty"}
};
var options1 = new Dictionary<string, object>{
{"face_field", "age"},
{"max_face_num", 2},
{"face_type", "LIVE"},
{"liveness_control", "LOW"}
};
var result = client.Detect(image, imageType,options);
textBox1.Text = result.ToString();
} catch (Exception ex)
{ MessageBox.Show(ex.Message); }
}
}
在实现人脸比对时使用 JArray
和 JObject
(这两者都来自 Newtonsoft.Json 或其他类似的 JSON 库)来构建一个 JSON 数组 faces
。这个数组包含两个 JSON 对象,每个对象代表一张图片,包含图片的 Base64 编码、图片类型、人脸类型、质量控制和活跃度控制等属性。调用 client
对象的 Match
方法,并将之前构建的 faces
JSON 数组作为参数传递。该方法返回一个结果,存储在 result
变量中。
private void button2_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBox2.Text) || string.IsNullOrEmpty(textBox3.Text))
{
MessageBox.Show("请选择要对比的人脸图片");
return;
}
try
{
string path1=textBox2.Text;
string path2=textBox3.Text;
var faces = new JArray
{
new JObject
{
{"image", ReadImg(path1)},
{"image_type", "BASE64"},
{"face_type", "LIVE"},
{"quality_control", "LOW"},
{"liveness_control", "NONE"},
},
new JObject
{
{"image", ReadImg(path2)},
{"image_type", "BASE64"},
{"face_type", "LIVE"},
{"quality_control", "LOW"},
{"liveness_control", "NONE"},
}
};
// 带参数调用人脸比对
var result = client.Match(faces);
textBox1.Text = result.ToString();
}
catch (Exception ex)
{ }
}
人脸对比时需要从本地导入两张图像进行比对,设置文件过滤器来完成该功能。
private void button3_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = "D:\\";
dialog.Filter = "所有文件|*.*";
dialog.RestoreDirectory = true;
dialog.FilterIndex = 2;
if (dialog.ShowDialog() == DialogResult.OK)
{
if (string.IsNullOrEmpty(textBox2.Text))
{
textBox2.Text = dialog.FileName;
}
else
{
textBox3.Text = dialog.FileName;
}
}
}
代码运行后结果如下:
三、实验难点
实验过程在需要利用到BaiduAI的人脸识别技术,在代码设计的过程中,需要到百度智能云官网中找到人脸识别技术,查看相关的调用方法和要求。例如,请求格式化Content-Type为application/json
,通过json
格式化请求体。需要比对的图片需经过Base64编码
,图片的base64编码指将图片数据编码成一串字符串,使用该字符串代替图像地址。可以首先得到图片的二进制,然后用Base64格式编码即可。目前只支持PNG、JPG、JPEG、BMP图片,不支持GIF。
四、代码实现
using Baidu.Aip.Face;
using BaiduAI.Common;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace BaiduAI
{
public partial class Form1 : Form
{
private string APP_ID = "33711276";
private string API_KEY = "1nhS4AcrLFffxqDKB73bb1U7";
private string SECRET_KEY = "rtnRFv5RcE0dMxBWqmL6PX3LYwVAdETW";
private Face client = null;
private bool IsStart = false;
private FaceLocation location = null;
public Form1()
{
InitializeComponent();
client = new Face(API_KEY, SECRET_KEY);
}
public string ConvertImageToBase64(Image file)
{
using (MemoryStream memoryStream = new MemoryStream())
{
file.Save(memoryStream, file.RawFormat);
byte[] imageBytes = memoryStream.ToArray();
return Convert.ToBase64String(imageBytes);
}
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = "E:\\教学\\VS222302 - desktop\\baiduAIFaceIdentify-master\\baiduAIFaceIdentify-master\\BaiduAI\\BaiduAI\\bin\\Debug";
dialog.Filter = "所有文件|*.*";
dialog.RestoreDirectory = true;
dialog.FilterIndex = 1;
if (dialog.ShowDialog() == DialogResult.OK)
{
string filename = dialog.FileName;
try
{
Image im = Image.FromFile(filename);
var image = ConvertImageToBase64(im);
string imageType = "BASE64";
// 如果有可选参数
var options = new Dictionary<string, object>{
//{"max_face_num", 2},
{"face_field", "age,beauty"},
{"face_fields", "age,qualities,beauty"}
};
var options1 = new Dictionary<string, object>{
{"face_field", "age"},
{"max_face_num", 2},
{"face_type", "LIVE"},
{"liveness_control", "LOW"}
};
var result = client.Detect(image, imageType,options);
textBox1.Text = result.ToString();
} catch (Exception ex)
{ MessageBox.Show(ex.Message); }
}
}
public string ReadImg(string img)
{
return Convert.ToBase64String(File.ReadAllBytes(img));
}
private void button2_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(textBox2.Text) || string.IsNullOrEmpty(textBox3.Text))
{
MessageBox.Show("请选择要对比的人脸图片");
return;
}
try
{
string path1=textBox2.Text;
string path2=textBox3.Text;
var faces = new JArray
{
new JObject
{
{"image", ReadImg(path1)},
{"image_type", "BASE64"},
{"face_type", "LIVE"},
{"quality_control", "LOW"},
{"liveness_control", "NONE"},
},
new JObject
{
{"image", ReadImg(path2)},
{"image_type", "BASE64"},
{"face_type", "LIVE"},
{"quality_control", "LOW"},
{"liveness_control", "NONE"},
}
};
// 带参数调用人脸比对
var result = client.Match(faces);
textBox1.Text = result.ToString();
}
catch (Exception ex)
{ }
}
private void button3_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.InitialDirectory = "D:\\";
dialog.Filter = "所有文件|*.*";
dialog.RestoreDirectory = true;
dialog.FilterIndex = 2;
if (dialog.ShowDialog() == DialogResult.OK)
{
if (string.IsNullOrEmpty(textBox2.Text))
{
textBox2.Text = dialog.FileName;
}
else
{
textBox3.Text = dialog.FileName;
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
System.Environment.Exit(0);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox3_TextChanged(object sender, EventArgs e)
{
}
}
}
五、实验总结
实验总共涉及到下面几个技术:
- API 集成:代码中包含了与百度的人脸识别API进行交互的初始化逻辑。这通过
Face
类的实例client
完成,该类在构造函数中被初始化,并传入API密钥和秘密密钥。 - 文件选择:使用
OpenFileDialog
类让用户从文件系统中选择一个图像文件。这解决了用户如何指定要处理的图像文件的问题。 - 图像编码:
ConvertImageToBase64
方法将图像转换为Base64编码的字符串。许多API要求图像数据以Base64字符串的形式提供。 - 参数配置:在调用API之前,使用
Dictionary<string, object>
配置了一系列参数这些参数指定了API应该返回哪些人脸字段(例如年龄、美丽度等)以及可能的其他选项(例如要检测的最大人脸数量)。 - 异常处理:使用
try
块来捕获在读取和处理图像文件时可能发生的任何异常。 - 窗体编程:代码是基于Windows窗体(WinForms)的,它使用.NET Framework中的
Form
类来创建用户界面。 - 资源管理:使用
using
语句来确保MemoryStream
对象在使用后被正确释放,这是一种良好的资源管理实践。