Unity人脸检测,离线通用人脸检测,基于OpenCvForUnity插件,实现摄像头画面通用人脸检测功能,适合小白入门(一)

本文参考博客   https://www.jianshu.com/p/7938864e9875

 

Unity离线摄像头画面通用人脸检测,摆脱了BaiduAI的次数限制,也不需要联网

此工程只能识别摄像头画面中脸的位置和数量,不能识别人脸的ID,即不能区分出当前识别到的人脸是谁

 

想要实现识别对应人脸的ID,即分得清张三和李四,实现真正的人脸识别功能,请查看本人其他博客,具体哪篇,我也不记得了,滑稽

 

文末附此次工程文件链接

 

效果:

 

 

 

首先需要导入插件 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>();    //获取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<FaceDetect>().DetectFace();

如下图所示:

 

保存后

大功告成

 

工程文件500M,这么大,主要是OpenCvForUnity插件解压后有1个G...

压缩后500M

工程链接:

链接:https://pan.baidu.com/s/1RbNq24s6oAOJOxOCP_L-lg 
提取码:x43l 

 

 

 

 

  • 26
    点赞
  • 143
    收藏
    觉得还不错? 一键收藏
  • 42
    评论
要在Unity中检测人的轮廓,可以使用OpenCV for Unity插件。以下是一些步骤: 1. 下载和安装OpenCV for Unity插件(https://assetstore.unity.com/packages/tools/integration/opencv-for-unity-21088)。 2. 将图像作为纹理加载到Unity中。 3. 使用OpenCV for Unity插件中的"TextureToMat"功能将纹理转换为OpenCV Mat对象。 4. 使用OpenCV for Unity中的人脸检测功能检测人脸。 5. 使用OpenCV for Unity中的轮廓检测功能检测人的轮廓。 6. 将检测到的轮廓绘制到纹理上。 7. 将纹理显示在Unity场景中。 下面是一个代码示例,展示如何使用OpenCV for Unity插件进行人的轮廓检测: ``` using UnityEngine; using System.Collections; using OpenCVForUnity.CoreModule; using OpenCVForUnity.ImgprocModule; using OpenCVForUnity.UnityUtils; public class ContourDetectionExample : MonoBehaviour { // Use this for initialization void Start() { // Load the texture into a Texture2D object Texture2D texture = Resources.Load("test") as Texture2D; // Create a new Mat object from the texture Mat rgbaMat = new Mat(texture.height, texture.width, CvType.CV_8UC4); // Convert the texture to a Mat object Utils.texture2DToMat(texture, rgbaMat); // Convert the Mat object to grayscale Mat grayMat = new Mat(); Imgproc.cvtColor(rgbaMat, grayMat, Imgproc.COLOR_RGBA2GRAY); // Threshold the image to create a binary image Mat binaryMat = new Mat(); Imgproc.threshold(grayMat, binaryMat, 0, 255, Imgproc.THRESH_BINARY); // Find the contours in the binary image List<MatOfPoint> contours = new List<MatOfPoint>(); Mat hierarchy = new Mat(); Imgproc.findContours(binaryMat, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); // Draw the contours on the original image Imgproc.drawContours(rgbaMat, contours, -1, new Scalar(0, 255, 0, 255), 2); // Convert the Mat object back to a Texture2D object Texture2D outputTexture = new Texture2D(rgbaMat.cols(), rgbaMat.rows(), TextureFormat.RGBA32, false); Utils.matToTexture2D(rgbaMat, outputTexture); // Display the output texture in the scene GetComponent<Renderer>().material.mainTexture = outputTexture; } } ``` 这个代码示例加载了一个名为“test”的纹理,将其转换为Mat对象,然后使用OpenCV for Unity中的轮廓检测功能检测人的轮廓,并在原始图像上绘制轮廓。最后,将Mat对象转换回Texture2D对象并在场景中显示它。
评论 42
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值