Health/Assets/Scripts/UI/Component/FaceDetectManagerBase.cs

252 lines
9.3 KiB
C#

using Rect = OpenCVCompact.Rect;
using OpenCVCompact;
using System;
using UnityEngine;
using System.Collections.Generic;
using OpenCVForUnity.UnityUtils.Helper;
using dnn;
public abstract class FaceDetectManagerBase : MonoBehaviour
{
//Related To DNN Model
protected dnn.DNNUtils dnnUtils;
protected Texture2D _videoTexture;
protected double _lndmrkEstScore;
protected Mat mat4Process;
protected Mat grayMat4Process;
protected Mat mat4Display;
protected Mat mat4DisplayTexture;
protected Mat lndmrk;
protected MatOfRect detectionResult;
protected Rect detectRect;
protected int[] faceRect = new int[4];
//int webCamOrVideoOrImage = 0; //0 : webcam, 1 : video, 2 : image
int lndmrkMode = 1; //0: 51, 1: 84
int lndmrkLevel = 3;
bool kalmanOrNot = true;
float lndmrkEstScore;
protected FaceDetectUI panel;
protected Texture2D _cutTexture;
// Start is called before the first frame update
void Awake()
{
UIManager.Instance.LoadReset();
panel = UIManager.Instance.ShowPanel<FaceDetectUI>();
InitModel();
InitVariable();
InitMatHelper();
}
private void OnDestroy()
{
if (mat4Process != null)
mat4Process.Dispose();
if (grayMat4Process != null)
grayMat4Process.Dispose();
//if (img4Thread != null)
// img4Thread.Dispose();
if (lndmrk != null)
lndmrk.Dispose();
//if (lndmrk4Thread != null)
// lndmrk4Thread.Dispose();
if (mat4Display != null)
mat4Display.Dispose();
if (mat4DisplayTexture != null)
mat4DisplayTexture.Dispose();
//if (probExp != null)
// probExp.Dispose();
Dispose();
}
protected abstract void InitMatHelper();
protected abstract void Dispose();
private void InitVariable()
{
mat4Process = new Mat();
grayMat4Process = new Mat();
detectionResult = new MatOfRect();
detectRect = new Rect();
lndmrk = new Mat(2, 84, CvType.CV_32FC1, 0.0f);
InvokeRepeating("AnalyzingFace", 0f, 1f);
}
private bool InitModel()
{
dnnUtils = new dnn.DNNUtils();
string dnnLndmrkDetectModelFilePath;
string dnnFaceAttr7ModelFilePath;
string dnnFaceExpModelFilePath;
string multiTinyFaceDetectModelFilePath;
string YOLOV3DetectModelFilePath;
string YOLOV3DetectParamFilePath;
string YOLOV3DetectOpenCVModelFilePath;
string YOLOV3DetectOpenCVParamFilePath;
//Init Model File Path
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
dnnLndmrkDetectModelFilePath = Utils.getFilePath("FaceAnalyzer/face_lndmrk_detect_mobile.bin");
#else
dnnLndmrkDetectModelFilePath = Utils.getFilePath("FaceAnalyzer/face_lndmrk_detect.bin");
#endif
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
dnnFaceAttr7ModelFilePath = Utils.getFilePath("FaceAnalyzer/att_7_mobile.bin");
#else
dnnFaceAttr7ModelFilePath = Utils.getFilePath("FaceAnalyzer/att_7.bin");
#endif
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
dnnFaceExpModelFilePath = Utils.getFilePath("FaceAnalyzer/face_exp_mobile.bin");
#else
dnnFaceExpModelFilePath = Utils.getFilePath("FaceAnalyzer/face_exp.bin");
#endif
multiTinyFaceDetectModelFilePath = Utils.getFilePath("FaceAnalyzer/multi_tiny_face_detect_mobile.bin");
YOLOV3DetectModelFilePath = Utils.getFilePath("FaceAnalyzer/yolov3.bin");
YOLOV3DetectParamFilePath = Utils.getFilePath("FaceAnalyzer/yolov3.param");
YOLOV3DetectOpenCVModelFilePath = Utils.getFilePath("FaceAnalyzer/yolov3-tiny.weights");
YOLOV3DetectOpenCVParamFilePath = Utils.getFilePath("FaceAnalyzer/yolov3-tiny.cfg");
bool initFaceLndmrkRes;
initFaceLndmrkRes = dnnUtils.InitFaceLandmarkDetect(dnnLndmrkDetectModelFilePath);
if (initFaceLndmrkRes == false)
{
LogPrint.Error(dnnLndmrkDetectModelFilePath + " file is not loaded.");
LogPrint.Error(dnnLndmrkDetectModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder.");
}
dnnUtils.InitHeadPoseEstimation();
int initFaceAttrRes = dnnUtils.InitFaceAttribNet_7(dnnFaceAttr7ModelFilePath);
if (initFaceAttrRes <= 0)
{
LogPrint.Error(dnnFaceAttr7ModelFilePath + " file is not loaded.");
LogPrint.Error(dnnFaceAttr7ModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder.");
}
int initFaceExpRes = dnnUtils.InitFaceExpressionNet_7(dnnFaceExpModelFilePath);
if (initFaceExpRes <= 0)
{
LogPrint.Error(dnnFaceExpModelFilePath + " file is not loaded.");
LogPrint.Error(dnnFaceExpModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder.");
}
int initMultiTinyFaceDetectRes = dnnUtils.InitMultiTinyFaceDetector(multiTinyFaceDetectModelFilePath);
if (initMultiTinyFaceDetectRes <= 0)
{
LogPrint.Error(multiTinyFaceDetectModelFilePath + " file is not loaded.");
LogPrint.Error(multiTinyFaceDetectModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder.");
}
int initYOLOV3DetectRes = dnnUtils.InitYOLOV3Detector(YOLOV3DetectModelFilePath, YOLOV3DetectParamFilePath);
if (initYOLOV3DetectRes == -1)
{
LogPrint.Error(YOLOV3DetectModelFilePath + " file is not loaded.");
LogPrint.Error(YOLOV3DetectModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder.");
}
else if (initYOLOV3DetectRes == -2)
{
LogPrint.Error(YOLOV3DetectParamFilePath + " file is not loaded.");
LogPrint.Error(YOLOV3DetectParamFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder.");
}
dnnUtils.InitLabels_7();
dnnUtils.InitExpLabels_7();
dnnUtils.InitObjectLabels_21();
dnnUtils.InitKalmanFilter(10f);
return true;
}
protected abstract Mat GetMat();
//update
protected virtual void AnalyzingFace()
{
mat4Display = GetMat();
if (mat4Display == null)
return;
//mat4Display.copyTo(mat4Process);
mat4Process = PictureUtility.GetROIRect(mat4Display.clone(), out var roiRegion);
//Face Detect
panel.RefreshData(LandmarkDetect());
var point1 = new Point(roiRegion[0], roiRegion[1]);
var point2 = new Point(roiRegion[0] + roiRegion[2], roiRegion[0] + roiRegion[3]);
Imgproc.rectangle(mat4Display, point1, point2, new Scalar(255, 0, 0), 2);
DebugPint();
}
protected abstract void DebugPint();
protected Dictionary<string, string> LandmarkDetect()
{
if (dnnUtils.GetEstimateLandmarkSuccessOrNot() == false || lndmrkEstScore < 0.25) //If It Failed To Track Facial Landmark in Previous Frame
{
//Face Detect!!!
Imgproc.cvtColor(mat4Process, grayMat4Process, OpenCVCompact.Imgproc.COLOR_RGBA2GRAY); //Face Detection Should Use Gray Image
if (dnnUtils.DetectFace(grayMat4Process, detectionResult, 32, 1024, true)) //Detect Face
{
detectRect = detectionResult.toArray()[0];
faceRect[0] = detectRect.x; faceRect[1] = detectRect.y; faceRect[2] = detectRect.width; faceRect[3] = detectRect.height;
lndmrkEstScore = dnnUtils.EstimateFacialLandmark(mat4Process.nativeObj, ref faceRect[0], lndmrk.nativeObj, lndmrkMode, kalmanOrNot, lndmrkLevel);
}
}
else
{
//Track Facial Landmark If It Succeeded In Previous Frame
faceRect = dnnUtils.SquareFromInnerLandmark(lndmrk.nativeObj);
lndmrkEstScore = dnnUtils.EstimateFacialLandmark(mat4Process.nativeObj, ref faceRect[0], lndmrk.nativeObj, lndmrkMode, kalmanOrNot, lndmrkLevel);
}
Mat prob = new Mat();
Dictionary<string, string> retVal = null;
if (dnnUtils.EstFaceAttribNet_7(mat4Process.nativeObj, lndmrk.nativeObj, CvType.COLOR_RGBA, prob.nativeObj) == true)
{
dnnUtils.ParseEstFaceAttrib_7(prob);
string text = string.Empty;
retVal = new Dictionary<string, string>(dnnUtils.dnnFaceAttribRes_7);
int idx = 0;
foreach (var pair in dnnUtils.dnnFaceAttribRes_7)
{
string tmp;
if (idx % 2 == 0)
tmp = string.Format("[{0}] : {1}\n", pair.Key, pair.Value);
else
tmp = string.Format("[{0}] : {1}\t\t", pair.Key, pair.Value);
text = string.Concat(text, tmp);
idx = idx + 1;
}
}
prob.Dispose();
return retVal;
}
}