本文参考博客 https://www.jianshu.com/p/7938864e9875
效果:
首先需要导入插件 OpenCV for Unity 2.2.6.unitypackage,本人用的2.2.6版本,
插件链接:https://pan.baidu.com/s/1AocvVjlGqnLeD9ezk8idBw
提取码:9dfy
本插件仅供学习交流使用,禁止商用
我们新建一个场景,取名FaceDetect,将窗口大小设为640x480(窗口大小根据需求自定义)
将Main Camera的Projection设为Orthographic
新建一个Canvas,将Canvas的Render Mode 设为 Screen Space - Camera
新建一个Quad 操作: 在 Hierarchy面板 空白处右键--> 3D Object--> Quad
将Quad设为Canvas 的子物体,并将Quad的Scale设为640,480,1
如下图所示
此时为Quad添加WebcamTextureToMacExample脚本,操作:选中Quad--> Add Component--> WebcamTextureToMacExample
其中Requested Device Name为摄像机名,不需要填写
Requested Width和Requested Height为获取画面的宽和高,默认即可
此时我们启动程序,已经可以获取到摄像头画面了
接下来是实现人脸识别:
此时我们新建一个C#脚本 取名:FaceDetect
将FaceDetect.cs同样添加到Quad物体上
打开FaceDetect.cs 添加引用:
using OpenCVForUnity;
using OpenCVForUnityExample;
上文添加的WebcamTextureToMacExample脚本就是OpenCvForUnity插件自带的获取摄像头画面的辅助类
既然是识别摄像头画面,首先我们需要获取到摄像头的画面,
打开WebcamTextureToMacExample.cs
将51行的rgbaMat变量改为公有变量,即添加Public修饰
既然需要识别人脸,我们需要人脸识别训练数据
通用人脸识别数据可从GitHub上下载,
链接:https://github.com/opencv/opencv
本文也提供了网盘链接:
链接:https://pan.baidu.com/s/1XiR811tPhPwBfSoS-ynw2w
提取码:wqaf
下载完后在路径data\haarcascades\下找到haarcascade_frontalface_alt2.xml文件
此包内有很多其他的训练数据,可根据自身需求尝试一下其他的文件
本工程已经导入了几个相关的训练数据可供使用
新建一个StreamingAssets文件夹
将haarcascade_frontalface_alt2.xml文件复制到该文件夹下
haarcascade_frontalface_alt2.xml即为通用的人脸识别训练数据文件
回到FaceDetect.cs脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using OpenCVForUnity;
using OpenCVForUnityExample;
public class FaceDetect : MonoBehaviour
{
WebCamTextureToMatExample webcamTexToMat = new WebCamTextureToMatExample(); //获取摄像头画面的辅助类
string faceXml_path; //人脸识别训练数据文件xml的路径
Mat gray; //灰度图,方便识别
MatOfRect faceRect; //识别到的人脸的区域
CascadeClassifier classifier; //人脸识别分类器
// Start is called before the first frame update
void Start()
{
webcamTexToMat = transform.GetComponent(); //获取WebCamTextureToMatExample
faceXml_path = Application.streamingAssetsPath + "/haarcascade_frontalface_alt2.xml"; //读取人脸识别训练数据xml
gray = new Mat(); //初始化Mat
faceRect = new MatOfRect(); //初始化识别到的人脸的区域
classifier = new CascadeClassifier(faceXml_path); //初始化人脸识别分类器
}
public void DetectFace()
{
//webcamTexToMat.rgbaMat为摄像头画面,Mat类型,Imgproc.COLOR_RGBA2GRAY为将RGBA画面转化为灰度图
Imgproc.cvtColor(webcamTexToMat.rgbaMat, gray, Imgproc.COLOR_RGBA2GRAY); //将获取到的摄像头画面转化为灰度图并赋值给gray
classifier.detectMultiScale(gray, faceRect, 1.1d, 2, 2, new Size(20, 20), new Size()); //检测gray中的人脸
OpenCVForUnity.Rect[] rects = faceRect.toArray();
for (int i = 0; i < rects.Length; i++)
{
Imgproc.rectangle(webcamTexToMat.rgbaMat, new Point(rects[i].x, rects[i].y), new Point(rects[i].x + rects[i].width, rects[i].y + rects[i].height), new Scalar(0, 255, 0, 255), 2); //在原本的画面中画框,框出人脸额位置,其中rects[i].x和rects[i].y为框的左上角的顶点,rects[i].width、rects[i].height即为框的宽和高
}
}
}
各个属性方法的作用看注释
其中classifier.detectMultiScale(gray, faceRect, 1.1d, 2, 2, new Size(20, 20), new Size());各个参数说明:
去官网看了一下说明,结合其他人的博客,
gray为输入的灰度图
faceRect为被检测到的物体的矩形向量组,保存有x,y,w,h四个参数,,比如我们检测到人脸,首先我们需要知道这个人脸的位置,其次,我们需要知道这个人脸的大小,那么(x,y)就是被检测到的人脸的左上角的坐标,而w,h分别代表宽度和高度
scaleFactor默认为1.1,scaleFactor的值必须大于1,这个参数的作用,好像与识别速度和精度有关,相当于一个阈值,当值越大,识别速度就越快,越容易识别出对象,但精度就会下降,可能会误识别成其他的对象,当值越小,识别速度就越慢,相应的精度就会提高,不容易出现将其他物体识别成我们需要的物体,但是容易造成一个都识别不到的情况。
第一个2为minNeighbors,看别人的博客说是指每个人脸起码被检测到两次才认为被检测到
第二个2为flags,新版的不需要,老版好像和性能优化有关,不知道理解的对不对
第一个new Size(20,20)为检测目标的最小尺寸minSzie,低于这个尺寸的对象不检测
第二个new Size()为目标的最大尺寸maxSize,高于这个尺寸的对象不检测
官网解释:https://docs.opencv.org/master/d1/de5/classcv_1_1CascadeClassifier.html
此时再回到WebcamTextureToMacExample.cs
找到228行的Update方法,将Imgproc.putText()注释掉,并添加代码
transform.GetComponent().DetectFace();
如下图所示:
保存后
大功告成
工程文件500M,这么大,主要是OpenCvForUnity插件解压后有1个G...
压缩后500M
工程链接:
链接:https://pan.baidu.com/s/1RbNq24s6oAOJOxOCP_L-lg
提取码:x43l