使用Accord.NET识别图片中的人脸数量
最近在看《C#神经网络编程》的时候,发现了一个使用C#检测图片中人脸的程序实例,就自己亲手用Sunny.UI搭建了一个WinForm项目实践了一遍,效果还可以,实例中检测识别人脸的框架类库用的是 Accord.NET Framework,也是基于C#语言编写的。
1. 项目搭建
新建一个WinForm项目,引入界面类库Sunny.UI,就是为了界面能漂亮一些,不显得土气,之后Nuget安装 Accord.Imaging,Accord.Vision,两个依赖包。安装完之后就可以写程序了。界面样式如下:
2. 界面概述
界面包括一个pictureBox控件,用于加载显示待检测的图片,网络图片按钮用于加载网络图片,本地图片则用于加载本地的图片,人脸识别检测用于开始检测动作的触发,模式的combobox控件是用于对象检测程序的搜索选项。范围的combobox控件是选择搜索识别的范围:是从一个大的搜索窗口开始,逐步扩大到较小的搜索窗口。还是从较小的搜索窗口开始,逐步扩大到较大的搜索窗口。并行复选框checkBox是用来选择是否用多线程并发来执行检测程序。
3. 功能代码
功能代码挺简单的,就是打开一个文件选择对话框并选择一个图片文件,之后通过配置HaarObjectDetector的实例对象,来实现人脸识别。识别之后再通过RectanglesMarker 实例对象在原图中标记出检测的人脸,而后返回标记后的图片。
public partial class MainForm : UIForm
{
Bitmap picture = Resources.faceOne;
HaarObjectDetector detector;
public MainForm()
{
InitializeComponent();
this.pictureBox_Images.Image = picture;
this.comboBox_mode.DataSource = Enum.GetValues(typeof(ObjectDetectorSearchMode));
this.comboBox_scaling.DataSource = Enum.GetValues(typeof(ObjectDetectorScalingMode));
comboBox_mode.SelectedItem = ObjectDetectorSearchMode.NoOverlap;
comboBox_scaling.SelectedItem = ObjectDetectorScalingMode.SmallerToGreater;
this.uiSymbolLabel_statue.Text = "准备就绪,请选择合适的参数选项开始进行人脸检测......";
HaarCascade cascade = new FaceHaarCascade();
detector = new HaarObjectDetector(cascade, 30);
}
/// <summary>
/// 读取文件到字节流
/// </summary>
/// <param name="imagepath"></param>
/// <returns></returns>
public byte[] GetPictureData(string imagepath)
{
FileStream FileStream = new FileStream(imagepath, FileMode.Open);
byte[] byData = new byte[FileStream.Length];
FileStream.Read(byData, 0, byData.Length);
FileStream.Close();
return byData;
}
/// <summary>
/// 打开本地文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void uiButton_fileImg_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.Filter = "图片文件(*.jpg;*.jpeg)|*.jpg;*.jpg|所有文件|*.*";
ofd.ValidateNames = true;
ofd.CheckPathExists = true;
ofd.CheckFileExists = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
string strFileName = ofd.FileName;
uiTextBox_urlfilePath.Text = strFileName;
using (MemoryStream mem = new MemoryStream(GetPictureData(strFileName)))
{
using (var image = Image.FromStream(mem))
{
this.pictureBox_Images.Image = this.picture = new Bitmap(image);
}
}
}
}
/// <summary>
/// 执行人脸检测
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void uiButton_detect_Click(object sender, EventArgs e)
{
detector.SearchMode = (ObjectDetectorSearchMode)comboBox_mode.SelectedValue;
detector.ScalingMode = (ObjectDetectorScalingMode)comboBox_scaling.SelectedValue;
detector.ScalingFactor = 1.5f;
detector.UseParallelProcessing = this.uiCheckBox_parallel.Checked;
detector.Suppression = 2;
Stopwatch sw = Stopwatch.StartNew();
// 检测人脸,返回检测数量
Rectangle[] objects = detector.ProcessFrame(picture);
sw.Stop();
// 如果识别出了人脸,则标记原图,并返回标记后的图片。
if (objects.Length > 0)
{
RectanglesMarker marker = new RectanglesMarker(objects, Color.Red);
this.pictureBox_Images.Image = marker.Apply(picture);
}
this.uiSymbolLabel_statue.Text = string.Format("在 {0} s 内,已经完成 {1} 个人脸识别对象的检测!", sw.Elapsed, objects.Length);
}
}
3. 算法概述
Accord.NET使用Viola-Jones对象检测算法,该算法在2001年被提出,尽管它可以被训练去发现各种各样的目标事物,但在这个框架中,它主要的用途是检测识别人脸,根据BSD许可证,该算法对学术和商业使用都是免费的。需要注意的是,有一些特定版本的Haar对象检测框架,已经由维奥拉和琼斯申请了专利,在商业使用时可能受到限制。
算法检测模式说明
- Default 将扫描整个图像。
- Single 只会检索一个对象。
- NoOverlap 如果一个物体已经在一个区域内被检测到,内部对象或重叠对象将不会被扫描两次。
- Average 如果几个物体位于彼此之间,就求它们的平均值。
一般来说模式选择Average ,缩放范围顺序选择GreaterToSmaller,检测结果会比较准确。