2023-11-24 18:39:53 +00:00
using Rect = OpenCVCompact . Rect ;
2023-11-20 15:10:51 +00:00
using OpenCVCompact ;
using System ;
2023-11-20 01:56:30 +00:00
using UnityEngine ;
2023-11-20 15:10:51 +00:00
using System.Collections.Generic ;
2023-11-28 19:05:48 +00:00
using OpenCVForUnity.UnityUtils.Helper ;
using dnn ;
2023-11-20 01:56:30 +00:00
2023-11-28 19:05:48 +00:00
public abstract class FaceDetectManagerBase : MonoBehaviour
2023-11-20 01:56:30 +00:00
{
2023-11-20 15:10:51 +00:00
//Related To DNN Model
2023-11-28 19:05:48 +00:00
protected dnn . DNNUtils dnnUtils ;
2023-11-29 07:59:38 +00:00
protected Texture2D _videoTexture ;
2023-11-28 19:05:48 +00:00
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 ] ;
2023-11-21 07:53:52 +00:00
2023-11-24 18:39:53 +00:00
//int webCamOrVideoOrImage = 0; //0 : webcam, 1 : video, 2 : image
2023-11-21 07:53:52 +00:00
int lndmrkMode = 1 ; //0: 51, 1: 84
int lndmrkLevel = 3 ;
bool kalmanOrNot = true ;
float lndmrkEstScore ;
2023-11-20 15:10:51 +00:00
2023-11-28 19:05:48 +00:00
protected FaceDetectUI panel ;
2023-11-29 07:59:38 +00:00
protected Texture2D _cutTexture ;
2023-11-20 15:10:51 +00:00
2023-11-20 01:56:30 +00:00
// Start is called before the first frame update
2023-11-20 15:10:51 +00:00
void Awake ( )
2023-11-20 01:56:30 +00:00
{
UIManager . Instance . LoadReset ( ) ;
2023-11-20 15:10:51 +00:00
panel = UIManager . Instance . ShowPanel < FaceDetectUI > ( ) ;
InitModel ( ) ;
InitVariable ( ) ;
2023-11-28 19:05:48 +00:00
InitMatHelper ( ) ;
2023-11-20 15:10:51 +00:00
}
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 ( ) ;
2023-11-21 07:53:52 +00:00
if ( mat4DisplayTexture ! = null )
mat4DisplayTexture . Dispose ( ) ;
2023-11-20 15:10:51 +00:00
//if (probExp != null)
// probExp.Dispose();
2023-11-29 07:59:38 +00:00
Dispose ( ) ;
2023-11-20 15:10:51 +00:00
}
2023-11-28 19:05:48 +00:00
protected abstract void InitMatHelper ( ) ;
2023-11-29 07:59:38 +00:00
protected abstract void Dispose ( ) ;
2023-11-20 15:10:51 +00:00
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 ) ;
2023-11-21 03:02:31 +00:00
InvokeRepeating ( "AnalyzingFace" , 0f , 1f ) ;
2023-11-20 15:10:51 +00:00
}
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 )
{
2023-11-24 05:13:10 +00:00
LogPrint . Error ( dnnLndmrkDetectModelFilePath + " file is not loaded." ) ;
2023-11-24 18:39:53 +00:00
LogPrint . Error ( dnnLndmrkDetectModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder." ) ;
2023-11-20 15:10:51 +00:00
}
dnnUtils . InitHeadPoseEstimation ( ) ;
int initFaceAttrRes = dnnUtils . InitFaceAttribNet_7 ( dnnFaceAttr7ModelFilePath ) ;
if ( initFaceAttrRes < = 0 )
{
2023-11-24 05:13:10 +00:00
LogPrint . Error ( dnnFaceAttr7ModelFilePath + " file is not loaded." ) ;
2023-11-24 18:39:53 +00:00
LogPrint . Error ( dnnFaceAttr7ModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder." ) ;
2023-11-20 15:10:51 +00:00
}
int initFaceExpRes = dnnUtils . InitFaceExpressionNet_7 ( dnnFaceExpModelFilePath ) ;
if ( initFaceExpRes < = 0 )
{
2023-11-24 05:13:10 +00:00
LogPrint . Error ( dnnFaceExpModelFilePath + " file is not loaded." ) ;
2023-11-24 18:39:53 +00:00
LogPrint . Error ( dnnFaceExpModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder." ) ;
2023-11-20 15:10:51 +00:00
}
int initMultiTinyFaceDetectRes = dnnUtils . InitMultiTinyFaceDetector ( multiTinyFaceDetectModelFilePath ) ;
if ( initMultiTinyFaceDetectRes < = 0 )
{
2023-11-24 05:13:10 +00:00
LogPrint . Error ( multiTinyFaceDetectModelFilePath + " file is not loaded." ) ;
2023-11-24 18:39:53 +00:00
LogPrint . Error ( multiTinyFaceDetectModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder." ) ;
2023-11-20 15:10:51 +00:00
}
int initYOLOV3DetectRes = dnnUtils . InitYOLOV3Detector ( YOLOV3DetectModelFilePath , YOLOV3DetectParamFilePath ) ;
if ( initYOLOV3DetectRes = = - 1 )
{
2023-11-24 05:13:10 +00:00
LogPrint . Error ( YOLOV3DetectModelFilePath + " file is not loaded." ) ;
2023-11-24 18:39:53 +00:00
LogPrint . Error ( YOLOV3DetectModelFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder." ) ;
2023-11-20 15:10:51 +00:00
}
else if ( initYOLOV3DetectRes = = - 2 )
{
2023-11-24 05:13:10 +00:00
LogPrint . Error ( YOLOV3DetectParamFilePath + " file is not loaded." ) ;
2023-11-24 18:39:53 +00:00
LogPrint . Error ( YOLOV3DetectParamFilePath + " file is not existed on StreamingAssets Folder. Please copy from “Assets/FaceAnalyzer/StreamingAssets/” to “Assets/StreamingAssets/” folder." ) ;
2023-11-20 15:10:51 +00:00
}
dnnUtils . InitLabels_7 ( ) ;
dnnUtils . InitExpLabels_7 ( ) ;
dnnUtils . InitObjectLabels_21 ( ) ;
dnnUtils . InitKalmanFilter ( 10f ) ;
return true ;
}
2023-11-28 19:05:48 +00:00
protected abstract Mat GetMat ( ) ;
//update
protected virtual void AnalyzingFace ( )
2023-11-20 15:10:51 +00:00
{
2023-11-28 19:05:48 +00:00
mat4Display = GetMat ( ) ;
if ( mat4Display = = null )
2023-11-20 15:10:51 +00:00
return ;
2023-11-21 07:53:52 +00:00
//mat4Display.copyTo(mat4Process);
2023-11-28 19:05:48 +00:00
mat4Process = PictureUtility . GetROIRect ( mat4Display . clone ( ) , out var roiRegion ) ;
2023-11-20 15:10:51 +00:00
//Face Detect
panel . RefreshData ( LandmarkDetect ( ) ) ;
2023-11-21 07:53:52 +00:00
2023-11-28 19:05:48 +00:00
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 ( ) ;
2023-11-20 15:10:51 +00:00
}
2023-11-28 19:05:48 +00:00
protected abstract void DebugPint ( ) ;
protected Dictionary < string , string > LandmarkDetect ( )
2023-11-20 15:10:51 +00:00
{
2023-11-21 07:53:52 +00:00
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 ) ;
}
2023-11-20 15:10:51 +00:00
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 ;
2023-11-20 01:56:30 +00:00
}
}