MirzkisD1Ex0 1 year ago
parent
commit
dff97c3112

+ 303 - 0
Materials/MediaPipe/人体骨骼识别/WebCamSource.cs

@@ -0,0 +1,303 @@
+// Copyright (c) 2021 homuler
+//
+// Use of this source code is governed by an MIT-style
+// license that can be found in the LICENSE file or at
+// https://opensource.org/licenses/MIT.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using UnityEngine;
+
+#if UNITY_ANDROID
+using UnityEngine.Android;
+#endif
+
+namespace Mediapipe.Unity
+{
+  public class WebCamSource : ImageSource
+  {
+    private readonly int _preferableDefaultWidth = 1280;
+
+    private const string _TAG = nameof(WebCamSource);
+
+    private readonly ResolutionStruct[] _defaultAvailableResolutions;
+
+    public WebCamSource(int preferableDefaultWidth, ResolutionStruct[] defaultAvailableResolutions)
+    {
+      _preferableDefaultWidth = preferableDefaultWidth;
+      _defaultAvailableResolutions = defaultAvailableResolutions;
+    }
+
+    private static readonly object _PermissionLock = new object();
+    private static bool _IsPermitted = false;
+
+    private WebCamTexture _webCamTexture;
+    private WebCamTexture webCamTexture
+    {
+      get => _webCamTexture;
+      set
+      {
+        if (_webCamTexture != null)
+        {
+          _webCamTexture.Stop();
+        }
+        _webCamTexture = value;
+      }
+    }
+
+    public override int textureWidth => !isPrepared ? 0 : webCamTexture.width;
+    public override int textureHeight => !isPrepared ? 0 : webCamTexture.height;
+
+    public override bool isVerticallyFlipped => isPrepared && webCamTexture.videoVerticallyMirrored;
+    public override bool isFrontFacing => isPrepared && (webCamDevice is WebCamDevice valueOfWebCamDevice) && valueOfWebCamDevice.isFrontFacing;
+    public override RotationAngle rotation => !isPrepared ? RotationAngle.Rotation0 : (RotationAngle)webCamTexture.videoRotationAngle;
+
+    private WebCamDevice? _webCamDevice;
+    private WebCamDevice? webCamDevice
+    {
+      get => _webCamDevice;
+      set
+      {
+        if (_webCamDevice is WebCamDevice valueOfWebCamDevice)
+        {
+          if (value is WebCamDevice valueOfValue && valueOfValue.name == valueOfWebCamDevice.name)
+          {
+            // not changed
+            return;
+          }
+        }
+        else if (value == null)
+        {
+          // not changed
+          return;
+        }
+        _webCamDevice = value;
+        resolution = GetDefaultResolution();
+      }
+    }
+    public override string sourceName => (webCamDevice is WebCamDevice valueOfWebCamDevice) ? valueOfWebCamDevice.name : null;
+
+    private WebCamDevice[] _availableSources;
+    private WebCamDevice[] availableSources
+    {
+      get
+      {
+        if (_availableSources == null)
+        {
+          _availableSources = WebCamTexture.devices;
+        }
+
+        return _availableSources;
+      }
+      set => _availableSources = value;
+    }
+
+    public override string[] sourceCandidateNames => availableSources?.Select(device => device.name).ToArray();
+
+#pragma warning disable IDE0025
+    public override ResolutionStruct[] availableResolutions
+    {
+      get
+      {
+#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
+        if (webCamDevice is WebCamDevice valueOfWebCamDevice) {
+          return valueOfWebCamDevice.availableResolutions.Select(resolution => new ResolutionStruct(resolution)).ToArray();
+        }
+#endif
+        return webCamDevice == null ? null : _defaultAvailableResolutions;
+      }
+    }
+#pragma warning restore IDE0025
+
+    public override bool isPrepared => webCamTexture != null;
+    public override bool isPlaying => webCamTexture != null && webCamTexture.isPlaying;
+
+    private IEnumerator Initialize()
+    {
+      yield return GetPermission();
+
+      if (!_IsPermitted)
+      {
+        yield break;
+      }
+
+      if (webCamDevice != null)
+      {
+        yield break;
+      }
+
+      availableSources = WebCamTexture.devices;
+
+      if (availableSources != null && availableSources.Length > 0)
+      {
+        // webCamDevice = availableSources[0];
+
+        // 施工区
+        for (int i = 0; i < availableSources.Length; i++)
+        {
+          Debug.LogWarning(availableSources[i].name);
+          if (availableSources[i].name == "MX Brio") // 
+          {
+            webCamDevice = availableSources[i];
+            break;
+          }
+        }
+        // 施工区
+
+      }
+    }
+
+    private IEnumerator GetPermission()
+    {
+      lock (_PermissionLock)
+      {
+        if (_IsPermitted)
+        {
+          yield break;
+        }
+
+#if UNITY_ANDROID
+        if (!Permission.HasUserAuthorizedPermission(Permission.Camera))
+        {
+          Permission.RequestUserPermission(Permission.Camera);
+          yield return new WaitForSeconds(0.1f);
+        }
+#elif UNITY_IOS
+        if (!Application.HasUserAuthorization(UserAuthorization.WebCam)) {
+          yield return Application.RequestUserAuthorization(UserAuthorization.WebCam);
+        }
+#endif
+
+#if UNITY_ANDROID
+        if (!Permission.HasUserAuthorizedPermission(Permission.Camera))
+        {
+          Debug.LogWarning("Not permitted to use Camera");
+          yield break;
+        }
+#elif UNITY_IOS
+        if (!Application.HasUserAuthorization(UserAuthorization.WebCam)) {
+          Debug.LogWarning("Not permitted to use WebCam");
+          yield break;
+        }
+#endif
+        _IsPermitted = true;
+
+        yield return new WaitForEndOfFrame();
+      }
+    }
+
+    public override void SelectSource(int sourceId)
+    {
+      if (sourceId < 0 || sourceId >= availableSources.Length)
+      {
+        throw new ArgumentException($"Invalid source ID: {sourceId}");
+      }
+
+      webCamDevice = availableSources[sourceId];
+    }
+
+    public override IEnumerator Play()
+    {
+      yield return Initialize();
+      if (!_IsPermitted)
+      {
+        throw new InvalidOperationException("Not permitted to access cameras");
+      }
+
+      InitializeWebCamTexture();
+      webCamTexture.Play();
+      yield return WaitForWebCamTexture();
+    }
+
+    public override IEnumerator Resume()
+    {
+      if (!isPrepared)
+      {
+        throw new InvalidOperationException("WebCamTexture is not prepared yet");
+      }
+      if (!webCamTexture.isPlaying)
+      {
+        webCamTexture.Play();
+      }
+      yield return WaitForWebCamTexture();
+    }
+
+    public override void Pause()
+    {
+      if (isPlaying)
+      {
+        webCamTexture.Pause();
+      }
+    }
+
+    public override void Stop()
+    {
+      if (webCamTexture != null)
+      {
+        webCamTexture.Stop();
+      }
+      webCamTexture = null;
+    }
+
+    public override Texture GetCurrentTexture() => webCamTexture;
+
+    private ResolutionStruct GetDefaultResolution()
+    {
+      var resolutions = availableResolutions;
+      return resolutions == null || resolutions.Length == 0 ? new ResolutionStruct() : resolutions.OrderBy(resolution => resolution, new ResolutionStructComparer(_preferableDefaultWidth)).First();
+    }
+
+    private void InitializeWebCamTexture()
+    {
+      Stop();
+      if (webCamDevice is WebCamDevice valueOfWebCamDevice)
+      {
+        webCamTexture = new WebCamTexture(valueOfWebCamDevice.name, resolution.width, resolution.height, (int)resolution.frameRate);
+        return;
+      }
+      throw new InvalidOperationException("Cannot initialize WebCamTexture because WebCamDevice is not selected");
+    }
+
+    private IEnumerator WaitForWebCamTexture()
+    {
+      const int timeoutFrame = 2000;
+      var count = 0;
+      Debug.Log("Waiting for WebCamTexture to start");
+      yield return new WaitUntil(() => count++ > timeoutFrame || webCamTexture.width > 16);
+
+      if (webCamTexture.width <= 16)
+      {
+        throw new TimeoutException("Failed to start WebCam");
+      }
+    }
+
+    private class ResolutionStructComparer : IComparer<ResolutionStruct>
+    {
+      private readonly int _preferableDefaultWidth;
+
+      public ResolutionStructComparer(int preferableDefaultWidth)
+      {
+        _preferableDefaultWidth = preferableDefaultWidth;
+      }
+
+      public int Compare(ResolutionStruct a, ResolutionStruct b)
+      {
+        var aDiff = Mathf.Abs(a.width - _preferableDefaultWidth);
+        var bDiff = Mathf.Abs(b.width - _preferableDefaultWidth);
+        if (aDiff != bDiff)
+        {
+          return aDiff - bDiff;
+        }
+        if (a.height != b.height)
+        {
+          // prefer smaller height
+          return a.height - b.height;
+        }
+        // prefer smaller frame rate
+        return (int)(a.frameRate - b.frameRate);
+      }
+    }
+  }
+}

+ 2 - 0
Materials/MediaPipe/人体骨骼识别/readme.txt

@@ -0,0 +1,2 @@
+相机名可改
+.\Assets\MediaPipeUnity\Samples\Common\Scripts\ImageSource\WebCamSource.cs

+ 0 - 169
Materials/OpenCV/面部识别模块/FaceDetecter.cs

@@ -1,169 +0,0 @@
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-using UnityEngine.UI;
-
-// using OpenCVSharp;
-using OpenCVForUnity;
-using OpenCVForUnity.CoreModule;
-using OpenCVForUnity.ImgprocModule;
-using OpenCVForUnity.UnityUtils;
-using OpenCVForUnity.ObjdetectModule;
-
-namespace DiageoWhiskyBlending
-{
-  public class FaceDetecter : MonoBehaviour
-  {
-    private Mat gray; // 灰度图,方便识别
-    private Mat rotatedNewMat;
-    private MatOfRect faceRect; // 识别到的人脸的区域
-    private CascadeClassifier classifier; // 人脸识别分类器
-    private string cascadePath;
-
-    public float index = 0;
-
-    // ==================================================
-
-    private void Start()
-    {
-      // LogAllWebCam();
-      Init();
-    }
-
-    private void OnDestroy()
-    {
-      Dispose();
-    }
-
-    private void OnApplicationQuit()
-    {
-      Dispose();
-    }
-
-    // ==================================================
-
-    private void Init()
-    {
-      cascadePath = Application.streamingAssetsPath + "/haarcascade_frontalface_alt2.xml";
-      gray = new Mat(); // 初始化Mat
-      faceRect = new MatOfRect(); // 初始化识别到的人脸的区域
-      classifier = new CascadeClassifier(cascadePath); // 初始化人脸识别分类器
-
-      previewMat = new Mat();
-      previewTexture2D = new Texture2D(440, 440, TextureFormat.RGBA32, false);
-      return;
-    }
-
-    private void Dispose()
-    {
-      if (rotatedNewMat != null)
-      {
-        rotatedNewMat.Dispose();
-        rotatedNewMat = null;
-      }
-
-      if (previewMat != null)
-      {
-        previewMat.Dispose();
-        previewMat = null;
-      }
-      if (previewTexture2D != null)
-      {
-        Destroy(previewTexture2D);
-        previewTexture2D = null;
-      }
-      return;
-    }
-
-
-    public void DetectFace(Mat rgbaMat)
-    {
-      rotatedNewMat = MatRotate(rgbaMat.clone()); // 旋转原数据
-
-      Imgproc.cvtColor(rotatedNewMat, gray, Imgproc.COLOR_RGBA2GRAY); // 将获取到的摄像头画面转化为灰度图并赋值给gray
-
-      // mat/面部矩形向量组/识别精度越高越快越不准/面部识别次数2次以上算识别/?性能优化/最小检测尺寸/最大检测尺寸
-      classifier.detectMultiScale(gray, faceRect, 1.1d, 2, 2, new Size(20, 20), new Size()); // 检测gray中的人脸
-
-      OpenCVForUnity.CoreModule.Rect[] rects = faceRect.toArray();
-      if (rects.Length > 0)
-      {
-        for (int i = 0; i < rects.Length; i++)
-        {
-          Imgproc.rectangle(rotatedNewMat, 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即为框的宽和高
-        }
-
-        index += Time.deltaTime;
-        if (index > .3f)
-        {
-          Debug.Log("连续监测超过1s...[OK]");
-          GameManager.Instance.EnterLogicScene00();
-        }
-      }
-      else
-      {
-        // if (index > 0)
-        // {
-        //   index -= Time.deltaTime / 2;
-        //   if (index < 0)
-        //   {
-        index = 0;
-        // }
-        // }
-      }
-
-      // 深复制识别、画框数据并显示
-      UpdatePreview(rotatedNewMat);
-      return;
-    }
-
-    // ==================================================
-    // 预览画面
-    public Image ImagePreviewImage;
-    private Mat previewMat;
-    private Texture2D previewTexture2D;
-    private void UpdatePreview(Mat value)
-    {
-      if (!ImagePreviewImage)
-      {
-        return;
-      }
-      previewMat = value.clone();
-      Utils.matToTexture2D(previewMat, previewTexture2D);
-      ImagePreviewImage.sprite = Sprite.Create(previewTexture2D, new UnityEngine.Rect(0, 0, 440, 440), Vector2.zero);
-      return;
-    }
-
-    // ==================================================
-
-    /// <summary>
-    /// Mat旋转方法
-    /// </summary>
-    /// <param name="orginalMat"></param>
-    /// <returns></returns>
-    private Mat MatRotate(Mat orginalMat)
-    {
-      Mat rotatedMat = new Mat(orginalMat.height(), orginalMat.width(), CvType.CV_8UC4, new Scalar(0, 0, 0, 255)); // DEBUG:宽高可能相反
-
-      // mat旋转
-      Point center = new Point(orginalMat.cols() / 2f, orginalMat.rows() / 2f);
-      Mat mat = Imgproc.getRotationMatrix2D(center, 90, 1);
-      Imgproc.warpAffine(orginalMat, rotatedMat, mat, orginalMat.size());
-
-      return rotatedMat;
-    }
-
-    /// <summary>
-    /// 预览有多少相机
-    /// </summary>
-    private void LogAllWebCam()
-    {
-      Debug.Log($"Found {WebCamTexture.devices.Length} device...<color=green>[OK]</color>");
-      foreach (WebCamDevice webcamDevice in WebCamTexture.devices)
-      {
-        Debug.Log($"{webcamDevice.name}...<color=green>[OK]</color>");
-      }
-      return;
-    }
-  }
-}

+ 166 - 0
Materials/OpenCV/面部识别模块/FacialRecognitionHandler.cs

@@ -0,0 +1,166 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+// using OpenCVSharp;
+using OpenCVForUnity;
+using OpenCVForUnity.CoreModule;
+using OpenCVForUnity.ImgprocModule;
+using OpenCVForUnity.UnityUtils;
+using OpenCVForUnity.ObjdetectModule;
+
+/// <summary>
+/// 面部识别
+/// </summary>
+public class FacialRecognitionHandler : MonoBehaviour
+{
+  private Mat gray; // 灰度图,方便识别
+  private Mat rotatedNewMat;
+  private MatOfRect faceRect; // 识别到的人脸的区域
+  private CascadeClassifier classifier; // 人脸识别分类器
+  private string cascadePath = Application.streamingAssetsPath + "/haarcascade_frontalface_alt2.xml";
+
+  [SerializeField] private float timer = 0;
+
+  // ==================================================
+
+  private void Start() => Init();
+  private void OnDestroy() => Dispose();
+
+  // ==================================================
+
+  private void Init()
+  {
+    // LogAllWebCam();
+    gray = new Mat(); // 初始化Mat
+    faceRect = new MatOfRect(); // 初始化识别到的人脸的区域
+    classifier = new CascadeClassifier(cascadePath); // 初始化人脸识别分类器
+
+    previewMat = new Mat();
+    resultPreviewTexture2D = new Texture2D(440, 440, TextureFormat.RGBA32, false);
+    return;
+  }
+
+  // ==================================================
+  #region 资源释放
+
+  private void Dispose()
+  {
+    if (rotatedNewMat != null)
+    {
+      rotatedNewMat.Dispose();
+      rotatedNewMat = null;
+    }
+
+    if (previewMat != null)
+    {
+      previewMat.Dispose();
+      previewMat = null;
+    }
+    if (resultPreviewTexture2D != null)
+    {
+      Destroy(resultPreviewTexture2D);
+      resultPreviewTexture2D = null;
+    }
+    return;
+  }
+  #endregion
+
+  // ==================================================
+  #region 面部识别
+  public void DetectFace(Mat rgbaMat)
+  {
+    // rotatedNewMat = MatRotate(rgbaMat.clone()); // 旋转原数据
+    rotatedNewMat = rgbaMat.clone(); // 原数据
+
+    Imgproc.cvtColor(rotatedNewMat, gray, Imgproc.COLOR_RGBA2GRAY); // 将获取到的摄像头画面转化为灰度图并赋值给gray
+
+    // mat/面部矩形向量组/识别精度越高越快越不准/面部识别次数2次以上算识别/?性能优化/最小检测尺寸/最大检测尺寸
+    // classifier.detectMultiScale(gray, faceRect, 1.1d, 2, 2, new Size(20, 20), new Size()); // 检测gray中的人脸
+    classifier.detectMultiScale(gray, faceRect, 1.1d, 3, 2, new Size(20, 20), new Size());
+
+    OpenCVForUnity.CoreModule.Rect[] rects = faceRect.toArray();
+    if (rects.Length > 0)
+    {
+      for (int i = 0; i < rects.Length; i++)
+      {
+        Imgproc.rectangle(rotatedNewMat, 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即为框的宽和高
+      }
+
+      timer += Time.deltaTime;
+      if (timer > .2f)
+      {
+        Debug.Log("检测到面部");
+      }
+    }
+    else
+    {
+      // if (timer > 0) // 缓慢减少检测值
+      // {
+      //   timer -= Time.deltaTime / 2;
+      //   if (timer < 0)
+      //   {
+      //     timer = 0;
+      //   }
+      // }
+      timer = 0;
+    }
+
+    // 深复制识别、画框数据并显示
+    UpdateResultPreview(rotatedNewMat);
+    return;
+  }
+  #endregion
+
+  // ==================================================
+  #region 预览画面
+  [SerializeField] private Image resultPreviewImage;
+  private Mat previewMat;
+  private Texture2D resultPreviewTexture2D;
+  private void UpdateResultPreview(Mat value)
+  {
+    if (resultPreviewImage == null)
+    {
+      return;
+    }
+
+    previewMat = value.clone();
+    Utils.matToTexture2D(previewMat, resultPreviewTexture2D);
+    resultPreviewImage.sprite = Sprite.Create(resultPreviewTexture2D, new UnityEngine.Rect(0, 0, 440, 440), Vector2.zero);
+    return;
+  }
+  #endregion
+
+  // ==================================================
+
+  /// <summary>
+  /// Mat旋转方法
+  /// </summary>
+  /// <param name="orginalMat"></param>
+  /// <returns></returns>
+  private Mat MatRotate(Mat orginalMat)
+  {
+    Mat rotatedMat = new Mat(orginalMat.height(), orginalMat.width(), CvType.CV_8UC4, new Scalar(0, 0, 0, 255)); // DEBUG:宽高可能相反
+
+    // mat旋转
+    Point center = new Point(orginalMat.cols() / 2f, orginalMat.rows() / 2f);
+    Mat mat = Imgproc.getRotationMatrix2D(center, 90, 1);
+    Imgproc.warpAffine(orginalMat, rotatedMat, mat, orginalMat.size());
+
+    return rotatedMat;
+  }
+
+  /// <summary>
+  /// 预览有多少相机
+  /// </summary>
+  private void LogAllWebCam()
+  {
+    Debug.Log($"Found {WebCamTexture.devices.Length} device...<color=green>[OK]</color>");
+    foreach (WebCamDevice webcamDevice in WebCamTexture.devices)
+    {
+      Debug.Log($"{webcamDevice.name}...<color=green>[OK]</color>");
+    }
+    return;
+  }
+}

+ 0 - 783
Materials/OpenCV/面部识别模块/New Scene.unity

@@ -1,783 +0,0 @@
-%YAML 1.1
-%TAG !u! tag:unity3d.com,2011:
---- !u!29 &1
-OcclusionCullingSettings:
-  m_ObjectHideFlags: 0
-  serializedVersion: 2
-  m_OcclusionBakeSettings:
-    smallestOccluder: 5
-    smallestHole: 0.25
-    backfaceThreshold: 100
-  m_SceneGUID: 00000000000000000000000000000000
-  m_OcclusionCullingData: {fileID: 0}
---- !u!104 &2
-RenderSettings:
-  m_ObjectHideFlags: 0
-  serializedVersion: 9
-  m_Fog: 0
-  m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
-  m_FogMode: 3
-  m_FogDensity: 0.01
-  m_LinearFogStart: 0
-  m_LinearFogEnd: 300
-  m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
-  m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
-  m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
-  m_AmbientIntensity: 1
-  m_AmbientMode: 3
-  m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
-  m_SkyboxMaterial: {fileID: 0}
-  m_HaloStrength: 0.5
-  m_FlareStrength: 1
-  m_FlareFadeSpeed: 3
-  m_HaloTexture: {fileID: 0}
-  m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
-  m_DefaultReflectionMode: 0
-  m_DefaultReflectionResolution: 128
-  m_ReflectionBounces: 1
-  m_ReflectionIntensity: 1
-  m_CustomReflection: {fileID: 0}
-  m_Sun: {fileID: 0}
-  m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
-  m_UseRadianceAmbientProbe: 0
---- !u!157 &3
-LightmapSettings:
-  m_ObjectHideFlags: 0
-  serializedVersion: 12
-  m_GIWorkflowMode: 1
-  m_GISettings:
-    serializedVersion: 2
-    m_BounceScale: 1
-    m_IndirectOutputScale: 1
-    m_AlbedoBoost: 1
-    m_EnvironmentLightingMode: 0
-    m_EnableBakedLightmaps: 0
-    m_EnableRealtimeLightmaps: 0
-  m_LightmapEditorSettings:
-    serializedVersion: 12
-    m_Resolution: 2
-    m_BakeResolution: 40
-    m_AtlasSize: 1024
-    m_AO: 0
-    m_AOMaxDistance: 1
-    m_CompAOExponent: 1
-    m_CompAOExponentDirect: 0
-    m_ExtractAmbientOcclusion: 0
-    m_Padding: 2
-    m_LightmapParameters: {fileID: 0}
-    m_LightmapsBakeMode: 1
-    m_TextureCompression: 1
-    m_FinalGather: 0
-    m_FinalGatherFiltering: 1
-    m_FinalGatherRayCount: 256
-    m_ReflectionCompression: 2
-    m_MixedBakeMode: 2
-    m_BakeBackend: 1
-    m_PVRSampling: 1
-    m_PVRDirectSampleCount: 32
-    m_PVRSampleCount: 512
-    m_PVRBounces: 2
-    m_PVREnvironmentSampleCount: 256
-    m_PVREnvironmentReferencePointCount: 2048
-    m_PVRFilteringMode: 1
-    m_PVRDenoiserTypeDirect: 1
-    m_PVRDenoiserTypeIndirect: 1
-    m_PVRDenoiserTypeAO: 1
-    m_PVRFilterTypeDirect: 0
-    m_PVRFilterTypeIndirect: 0
-    m_PVRFilterTypeAO: 0
-    m_PVREnvironmentMIS: 1
-    m_PVRCulling: 1
-    m_PVRFilteringGaussRadiusDirect: 1
-    m_PVRFilteringGaussRadiusIndirect: 5
-    m_PVRFilteringGaussRadiusAO: 2
-    m_PVRFilteringAtrousPositionSigmaDirect: 0.5
-    m_PVRFilteringAtrousPositionSigmaIndirect: 2
-    m_PVRFilteringAtrousPositionSigmaAO: 1
-    m_ExportTrainingData: 0
-    m_TrainingDataDestination: TrainingData
-    m_LightProbeSampleCountMultiplier: 4
-  m_LightingDataAsset: {fileID: 0}
-  m_LightingSettings: {fileID: 0}
---- !u!196 &4
-NavMeshSettings:
-  serializedVersion: 2
-  m_ObjectHideFlags: 0
-  m_BuildSettings:
-    serializedVersion: 2
-    agentTypeID: 0
-    agentRadius: 0.5
-    agentHeight: 2
-    agentSlope: 45
-    agentClimb: 0.4
-    ledgeDropHeight: 0
-    maxJumpAcrossDistance: 0
-    minRegionArea: 2
-    manualCellSize: 0
-    cellSize: 0.16666667
-    manualTileSize: 0
-    tileSize: 256
-    accuratePlacement: 0
-    maxJobWorkers: 0
-    preserveTilesOutsideBounds: 0
-    debug:
-      m_Flags: 0
-  m_NavMeshData: {fileID: 0}
---- !u!1 &474530307
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 474530311}
-  - component: {fileID: 474530310}
-  - component: {fileID: 474530309}
-  - component: {fileID: 474530308}
-  m_Layer: 5
-  m_Name: Canvas
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!114 &474530308
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 474530307}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_IgnoreReversedGraphics: 1
-  m_BlockingObjects: 0
-  m_BlockingMask:
-    serializedVersion: 2
-    m_Bits: 4294967295
---- !u!114 &474530309
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 474530307}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_UiScaleMode: 0
-  m_ReferencePixelsPerUnit: 100
-  m_ScaleFactor: 1
-  m_ReferenceResolution: {x: 800, y: 600}
-  m_ScreenMatchMode: 0
-  m_MatchWidthOrHeight: 0
-  m_PhysicalUnit: 3
-  m_FallbackScreenDPI: 96
-  m_DefaultSpriteDPI: 96
-  m_DynamicPixelsPerUnit: 1
-  m_PresetInfoIsWorld: 0
---- !u!223 &474530310
-Canvas:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 474530307}
-  m_Enabled: 1
-  serializedVersion: 3
-  m_RenderMode: 1
-  m_Camera: {fileID: 1880489732}
-  m_PlaneDistance: 100
-  m_PixelPerfect: 0
-  m_ReceivesEvents: 1
-  m_OverrideSorting: 0
-  m_OverridePixelPerfect: 0
-  m_SortingBucketNormalizedSize: 0
-  m_AdditionalShaderChannelsFlag: 0
-  m_SortingLayerID: 0
-  m_SortingOrder: 0
-  m_TargetDisplay: 0
---- !u!224 &474530311
-RectTransform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 474530307}
-  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 0, y: 0, z: 0}
-  m_ConstrainProportionsScale: 0
-  m_Children:
-  - {fileID: 1399225159}
-  m_Father: {fileID: 0}
-  m_RootOrder: 2
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
-  m_AnchorMin: {x: 0, y: 0}
-  m_AnchorMax: {x: 0, y: 0}
-  m_AnchoredPosition: {x: 0, y: 0}
-  m_SizeDelta: {x: 0, y: 0}
-  m_Pivot: {x: 0, y: 0}
---- !u!1 &850486454
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 850486455}
-  - component: {fileID: 850486457}
-  - component: {fileID: 850486456}
-  m_Layer: 0
-  m_Name: Text (Legacy)
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!224 &850486455
-RectTransform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 850486454}
-  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children: []
-  m_Father: {fileID: 2054611989}
-  m_RootOrder: 0
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
-  m_AnchorMin: {x: 0, y: 1}
-  m_AnchorMax: {x: 1, y: 1}
-  m_AnchoredPosition: {x: 0, y: 0}
-  m_SizeDelta: {x: 0, y: 60}
-  m_Pivot: {x: 0.5, y: 0}
---- !u!114 &850486456
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 850486454}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_Material: {fileID: 0}
-  m_Color: {r: 1, g: 1, b: 1, a: 1}
-  m_RaycastTarget: 1
-  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
-  m_Maskable: 1
-  m_OnCullStateChanged:
-    m_PersistentCalls:
-      m_Calls: []
-  m_FontData:
-    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
-    m_FontSize: 50
-    m_FontStyle: 0
-    m_BestFit: 0
-    m_MinSize: 5
-    m_MaxSize: 51
-    m_Alignment: 4
-    m_AlignByGeometry: 0
-    m_RichText: 1
-    m_HorizontalOverflow: 0
-    m_VerticalOverflow: 0
-    m_LineSpacing: 1
-  m_Text: Detect
---- !u!222 &850486457
-CanvasRenderer:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 850486454}
-  m_CullTransparentMesh: 1
---- !u!1 &1076477677
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 1076477680}
-  - component: {fileID: 1076477679}
-  - component: {fileID: 1076477678}
-  m_Layer: 0
-  m_Name: EventSystem
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!114 &1076477678
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1076477677}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_SendPointerHoverToParent: 1
-  m_HorizontalAxis: Horizontal
-  m_VerticalAxis: Vertical
-  m_SubmitButton: Submit
-  m_CancelButton: Cancel
-  m_InputActionsPerSecond: 10
-  m_RepeatDelay: 0.5
-  m_ForceModuleActive: 0
---- !u!114 &1076477679
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1076477677}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_FirstSelected: {fileID: 0}
-  m_sendNavigationEvents: 1
-  m_DragThreshold: 10
---- !u!4 &1076477680
-Transform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1076477677}
-  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children: []
-  m_Father: {fileID: 0}
-  m_RootOrder: 0
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &1359915752
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 1359915760}
-  - component: {fileID: 1359915761}
-  - component: {fileID: 1359915758}
-  - component: {fileID: 1359915762}
-  - component: {fileID: 1359915763}
-  m_Layer: 0
-  m_Name: Quad
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!114 &1359915758
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1359915752}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 954b04b952bb3b149ade5e248c1b0839, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  index: 0
-  PreviewImage: {fileID: 2054611990}
---- !u!224 &1359915760
-RectTransform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1359915752}
-  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children:
-  - {fileID: 1770240637}
-  m_Father: {fileID: 1399225159}
-  m_RootOrder: 0
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
-  m_AnchorMin: {x: 0, y: 0}
-  m_AnchorMax: {x: 0, y: 0}
-  m_AnchoredPosition: {x: 0, y: 0}
-  m_SizeDelta: {x: 0, y: 0}
-  m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1359915761
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1359915752}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_Material: {fileID: 0}
-  m_Color: {r: 1, g: 1, b: 1, a: 1}
-  m_RaycastTarget: 1
-  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
-  m_Maskable: 1
-  m_OnCullStateChanged:
-    m_PersistentCalls:
-      m_Calls: []
-  m_Sprite: {fileID: 0}
-  m_Type: 0
-  m_PreserveAspect: 0
-  m_FillCenter: 1
-  m_FillMethod: 4
-  m_FillAmount: 1
-  m_FillClockwise: 1
-  m_FillOrigin: 0
-  m_UseSpriteMesh: 0
-  m_PixelsPerUnitMultiplier: 1
---- !u!222 &1359915762
-CanvasRenderer:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1359915752}
-  m_CullTransparentMesh: 1
---- !u!114 &1359915763
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1359915752}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: a6535bbeb939e004b8e5cbad7ec84dd6, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
---- !u!1 &1399225158
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 1399225159}
-  - component: {fileID: 1399225160}
-  m_Layer: 5
-  m_Name: GameObject
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!224 &1399225159
-RectTransform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1399225158}
-  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children:
-  - {fileID: 1359915760}
-  - {fileID: 2054611989}
-  m_Father: {fileID: 474530311}
-  m_RootOrder: 0
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
-  m_AnchorMin: {x: 0, y: 0}
-  m_AnchorMax: {x: 1, y: 1}
-  m_AnchoredPosition: {x: 0, y: 0}
-  m_SizeDelta: {x: -400, y: -400}
-  m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &1399225160
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1399225158}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 8a8695521f0d02e499659fee002a26c2, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_Padding:
-    m_Left: 0
-    m_Right: 0
-    m_Top: 0
-    m_Bottom: 0
-  m_ChildAlignment: 0
-  m_StartCorner: 0
-  m_StartAxis: 0
-  m_CellSize: {x: 440, y: 440}
-  m_Spacing: {x: 100, y: 100}
-  m_Constraint: 0
-  m_ConstraintCount: 2
---- !u!1 &1770240636
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 1770240637}
-  - component: {fileID: 1770240639}
-  - component: {fileID: 1770240638}
-  m_Layer: 0
-  m_Name: Text (Legacy)
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!224 &1770240637
-RectTransform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1770240636}
-  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children: []
-  m_Father: {fileID: 1359915760}
-  m_RootOrder: 0
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
-  m_AnchorMin: {x: 0, y: 1}
-  m_AnchorMax: {x: 1, y: 1}
-  m_AnchoredPosition: {x: 0, y: 0}
-  m_SizeDelta: {x: 0, y: 60}
-  m_Pivot: {x: 0.5, y: 0}
---- !u!114 &1770240638
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1770240636}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_Material: {fileID: 0}
-  m_Color: {r: 1, g: 1, b: 1, a: 1}
-  m_RaycastTarget: 1
-  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
-  m_Maskable: 1
-  m_OnCullStateChanged:
-    m_PersistentCalls:
-      m_Calls: []
-  m_FontData:
-    m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
-    m_FontSize: 50
-    m_FontStyle: 0
-    m_BestFit: 0
-    m_MinSize: 5
-    m_MaxSize: 51
-    m_Alignment: 4
-    m_AlignByGeometry: 0
-    m_RichText: 1
-    m_HorizontalOverflow: 0
-    m_VerticalOverflow: 0
-    m_LineSpacing: 1
-  m_Text: Orginal
---- !u!222 &1770240639
-CanvasRenderer:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1770240636}
-  m_CullTransparentMesh: 1
---- !u!1 &1880489730
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 1880489733}
-  - component: {fileID: 1880489732}
-  - component: {fileID: 1880489731}
-  m_Layer: 0
-  m_Name: Main Camera
-  m_TagString: MainCamera
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!81 &1880489731
-AudioListener:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1880489730}
-  m_Enabled: 1
---- !u!20 &1880489732
-Camera:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1880489730}
-  m_Enabled: 1
-  serializedVersion: 2
-  m_ClearFlags: 2
-  m_BackGroundColor: {r: 0.26415092, g: 0.26415092, b: 0.26415092, a: 0}
-  m_projectionMatrixMode: 1
-  m_GateFitMode: 2
-  m_FOVAxisMode: 0
-  m_SensorSize: {x: 36, y: 24}
-  m_LensShift: {x: 0, y: 0}
-  m_FocalLength: 50
-  m_NormalizedViewPortRect:
-    serializedVersion: 2
-    x: 0
-    y: 0
-    width: 1
-    height: 1
-  near clip plane: 0.3
-  far clip plane: 1000
-  field of view: 60
-  orthographic: 1
-  orthographic size: 5
-  m_Depth: -1
-  m_CullingMask:
-    serializedVersion: 2
-    m_Bits: 4294967295
-  m_RenderingPath: -1
-  m_TargetTexture: {fileID: 0}
-  m_TargetDisplay: 0
-  m_TargetEye: 3
-  m_HDR: 1
-  m_AllowMSAA: 1
-  m_AllowDynamicResolution: 0
-  m_ForceIntoRT: 0
-  m_OcclusionCulling: 1
-  m_StereoConvergence: 10
-  m_StereoSeparation: 0.022
---- !u!4 &1880489733
-Transform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 1880489730}
-  m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: -10}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children: []
-  m_Father: {fileID: 0}
-  m_RootOrder: 1
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
---- !u!1 &2054611988
-GameObject:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  serializedVersion: 6
-  m_Component:
-  - component: {fileID: 2054611989}
-  - component: {fileID: 2054611991}
-  - component: {fileID: 2054611990}
-  m_Layer: 5
-  m_Name: NewMatImage
-  m_TagString: Untagged
-  m_Icon: {fileID: 0}
-  m_NavMeshLayer: 0
-  m_StaticEditorFlags: 0
-  m_IsActive: 1
---- !u!224 &2054611989
-RectTransform:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 2054611988}
-  m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
-  m_LocalPosition: {x: 0, y: 0, z: 0}
-  m_LocalScale: {x: 1, y: 1, z: 1}
-  m_ConstrainProportionsScale: 0
-  m_Children:
-  - {fileID: 850486455}
-  m_Father: {fileID: 1399225159}
-  m_RootOrder: 1
-  m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
-  m_AnchorMin: {x: 0, y: 0}
-  m_AnchorMax: {x: 0, y: 0}
-  m_AnchoredPosition: {x: 0, y: 0}
-  m_SizeDelta: {x: 0, y: 0}
-  m_Pivot: {x: 0.5, y: 0.5}
---- !u!114 &2054611990
-MonoBehaviour:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 2054611988}
-  m_Enabled: 1
-  m_EditorHideFlags: 0
-  m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
-  m_Name: 
-  m_EditorClassIdentifier: 
-  m_Material: {fileID: 0}
-  m_Color: {r: 1, g: 1, b: 1, a: 1}
-  m_RaycastTarget: 1
-  m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
-  m_Maskable: 1
-  m_OnCullStateChanged:
-    m_PersistentCalls:
-      m_Calls: []
-  m_Sprite: {fileID: 0}
-  m_Type: 0
-  m_PreserveAspect: 0
-  m_FillCenter: 1
-  m_FillMethod: 4
-  m_FillAmount: 1
-  m_FillClockwise: 1
-  m_FillOrigin: 0
-  m_UseSpriteMesh: 0
-  m_PixelsPerUnitMultiplier: 1
---- !u!222 &2054611991
-CanvasRenderer:
-  m_ObjectHideFlags: 0
-  m_CorrespondingSourceObject: {fileID: 0}
-  m_PrefabInstance: {fileID: 0}
-  m_PrefabAsset: {fileID: 0}
-  m_GameObject: {fileID: 2054611988}
-  m_CullTransparentMesh: 1

BIN
Materials/OpenCV/面部识别模块/OpenCVToolkit.unitypackage


+ 0 - 0
Materials/OpenCV/面部识别模块/haarcascade_frontalface_alt2.xml → Materials/OpenCV/面部识别模块/StreamingAssets/haarcascade_frontalface_alt2.xml


+ 223 - 0
Materials/OpenCV/面部识别模块/WebCamTextureProcesser.cs

@@ -0,0 +1,223 @@
+using OpenCVForUnity;
+using OpenCVForUnity.CoreModule;
+using OpenCVForUnity.ImgprocModule;
+using OpenCVForUnity.UnityUtils;
+
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+using UnityEngine.UI;
+
+/// <summary>
+/// WebCam色彩图处理
+/// </summary>
+public class WebCamTextureProcesser : MonoBehaviour
+{
+  public static WebCamTextureProcesser Instance;
+
+  private WebCamDevice webCamDevice;
+  private WebCamTexture webCamTexture;
+  private Mat rgbaMat;
+
+  private Color32[] colors;
+  private bool isInitWaiting = false;
+  private bool hasInitDone = false; // 如果Init完毕
+
+  // ==================================================
+
+  private void Awake() => Instance = this;
+  private void Start() => Init();
+  private void Update() => ProcessWebCamTexture();
+  private void OnDestroy() => Dispose();
+
+  // ==================================================
+
+  private void Init()
+  {
+    if (isInitWaiting)
+    {
+      return;
+    }
+    StartCoroutine(nameof(InitAction));
+    return;
+  }
+  private IEnumerator InitAction()
+  {
+    if (hasInitDone) // 防止重复安装
+    {
+      Dispose();
+    }
+    isInitWaiting = true;
+
+    CreateCamera(); // 创建相机
+
+    while (true)
+    {
+      if (webCamTexture.didUpdateThisFrame)
+      {
+        isInitWaiting = false;
+        hasInitDone = true;
+
+        if (colors == null || colors.Length != webCamTexture.width * webCamTexture.height) // 确定color尺寸
+        {
+          colors = new Color32[webCamTexture.width * webCamTexture.height];
+        }
+        if (orginalPreviewTexture2D == null || orginalPreviewTexture2D.width != webCamTexture.width || orginalPreviewTexture2D.height != webCamTexture.height) // 确定texture2d尺寸
+        {
+          orginalPreviewTexture2D = new Texture2D(webCamTexture.width, webCamTexture.height, TextureFormat.RGBA32, false);
+        }
+
+        rgbaMat = new Mat(webCamTexture.height, webCamTexture.width, CvType.CV_8UC4, new Scalar(0, 0, 0, 255)); // 高、宽
+
+        // UpdateOriginalPreview(); // ?这里为什么会有预览
+        break;
+      }
+      else
+      {
+        yield return null;
+      }
+    }
+    yield break;
+  }
+
+  // ==================================================
+  #region 色彩画面处理
+  private void ProcessWebCamTexture()
+  {
+    if (hasInitDone && webCamTexture.isPlaying && webCamTexture.didUpdateThisFrame)
+    {
+      Utils.webCamTextureToMat(webCamTexture, rgbaMat, colors);
+
+      transform.GetComponent<FacialRecognitionHandler>().DetectFace(rgbaMat); // 传入mat 检测人脸 // 会导致原数据反转?
+      UpdateOriginalPreview();
+    }
+    return;
+  }
+  #endregion
+
+  // ==================================================
+  #region 释放资源
+  private void Dispose()
+  {
+    isInitWaiting = false;
+    hasInitDone = false;
+
+    if (webCamTexture != null)
+    {
+      webCamTexture.Stop();
+      Destroy(webCamTexture);
+      webCamTexture = null;
+    }
+    if (rgbaMat != null)
+    {
+      rgbaMat.Dispose();
+      rgbaMat = null;
+    }
+    if (orginalPreviewTexture2D != null)
+    {
+      Destroy(orginalPreviewTexture2D);
+      orginalPreviewTexture2D = null;
+    }
+    return;
+  }
+  #endregion
+
+  // ==================================================
+  #region 创建、配置WebCamera
+  [SerializeField] private string requestedDeviceName = "MX Brio"; // "GC21 Video" // "Logitech BRIO"
+  private int requestedWidth = 440;
+  private int requestedHeight = 440;
+  private int requestedFPS = 30;
+  private void CreateCamera()
+  {
+    foreach (WebCamDevice device in WebCamTexture.devices)
+    {
+      if (device.name == requestedDeviceName)
+      {
+        webCamDevice = device;
+        webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
+        webCamTexture.Play();
+        Debug.Log($"[WTP] Name:{webCamTexture.deviceName} / Width:{webCamTexture.width} / Height:{webCamTexture.height} / FPS:{webCamTexture.requestedFPS}");
+        Debug.Log($"[WTP] VideoRotationAngle:{webCamTexture.videoRotationAngle} / VideoVerticallyMirrored:{webCamTexture.videoVerticallyMirrored} / IsFrongFacing:{webCamDevice.isFrontFacing}");
+        return;
+      }
+    }
+    return;
+  }
+  #endregion
+
+  // ==================================================
+  #region 预览画面
+  [SerializeField] private Image originalPreviewImage;
+  private Texture2D orginalPreviewTexture2D;
+  private void UpdateOriginalPreview()
+  {
+    if (originalPreviewImage == null)
+    {
+      return;
+    }
+
+    Utils.matToTexture2D(rgbaMat, orginalPreviewTexture2D, colors); // Mat更新为texture2d
+    // texture2D = RotateTexutre(texture2D, false);
+    originalPreviewImage.sprite = Sprite.Create(orginalPreviewTexture2D, new UnityEngine.Rect(0, 0, orginalPreviewTexture2D.width, orginalPreviewTexture2D.height), Vector2.zero);
+    return;
+  }
+  #endregion
+
+  // ==================================================
+  // 按钮
+
+  public void OnPlayButtonClick()
+  {
+    if (hasInitDone)
+    {
+      webCamTexture.Play();
+    }
+    return;
+  }
+
+  public void OnPauseButtonClick()
+  {
+    if (hasInitDone)
+    {
+      webCamTexture.Pause();
+    }
+    return;
+  }
+
+  public void OnStopButtonClick()
+  {
+    if (hasInitDone)
+    {
+      webCamTexture.Stop();
+    }
+    return;
+  }
+
+  // ==================================================
+  //  Texture画面旋转 // 不必要的 // 旋转处理在FaceDetecter中进行
+  // private Texture2D RotateTexutre(Texture2D originalTexture, bool clockwise)
+  // {
+  //   Color32[] original = originalTexture.GetPixels32();
+  //   Color32[] rotated = new Color32[original.Length];
+  //   int w = originalTexture.width;
+  //   int h = originalTexture.height;
+
+  //   int iRotated, iOriginal;
+
+  //   for (int j = 0; j < h; ++j)
+  //   {
+  //     for (int i = 0; i < w; ++i)
+  //     {
+  //       iRotated = (i + 1) * h - j - 1;
+  //       iOriginal = clockwise ? original.Length - 1 - (j * w + i) : j * w + i;
+  //       rotated[iRotated] = original[iOriginal];
+  //     }
+  //   }
+
+  //   Texture2D newTexture = new Texture2D(originalTexture.height, originalTexture.width, TextureFormat.RGBA32, false);
+  //   newTexture.SetPixels32(rotated);
+  //   newTexture.Apply();
+  //   return newTexture;
+  // }
+}

+ 0 - 229
Materials/OpenCV/面部识别模块/WebCamTextureToMat.cs

@@ -1,229 +0,0 @@
-using OpenCVForUnity;
-using OpenCVForUnity.CoreModule;
-using OpenCVForUnity.ImgprocModule;
-using OpenCVForUnity.UnityUtils;
-
-using System.Collections;
-using System.Collections.Generic;
-using UnityEngine;
-using UnityEngine.UI;
-
-namespace DiageoWhiskyBlending
-{
-  public class WebCamTextureToMat : MonoBehaviour
-  {
-    private WebCamDevice webCamDevice;
-    private WebCamTexture webCamTexture;
-    private Mat rgbaMat;
-
-    private Color32[] colors;
-    private bool isInitWaiting = false;
-    private bool hasInitDone = false; // 如果Init完毕
-
-    // ==================================================
-
-    private void Start()
-    {
-      Init();
-    }
-
-    private void Update()
-    {
-      if (hasInitDone && webCamTexture.isPlaying && webCamTexture.didUpdateThisFrame)
-      {
-        Utils.webCamTextureToMat(webCamTexture, rgbaMat, colors);
-        transform.GetComponent<FaceDetecter>().DetectFace(rgbaMat); // 传入mat 检测人脸 // 会导致原数据反转?
-
-        // UpdatePreview();
-      }
-    }
-
-    private void OnDestroy()
-    {
-      Dispose();
-    }
-
-    private void OnApplicationQuit()
-    {
-      Dispose();
-    }
-
-    // ==================================================
-
-    private void Init()
-    {
-      if (isInitWaiting)
-      {
-        return;
-      }
-      StartCoroutine(InitAction());
-      return;
-    }
-    private IEnumerator InitAction()
-    {
-      if (hasInitDone) // 防止重复安装
-      {
-        Dispose();
-      }
-      isInitWaiting = true;
-
-      CreateCamera(); // 创建相机
-
-      while (true)
-      {
-        if (webCamTexture.didUpdateThisFrame)
-        {
-          Debug.Log($"Name:{webCamTexture.deviceName} / Width:{webCamTexture.width} / Height:{webCamTexture.height} / FPS:{webCamTexture.requestedFPS}...<color=green>[OK]</color>");
-          Debug.Log($"VideoRotationAngle:{webCamTexture.videoRotationAngle} / VideoVerticallyMirrored:{webCamTexture.videoVerticallyMirrored} / IsFrongFacing:{webCamDevice.isFrontFacing}...<color=green>[OK]</color>");
-
-          isInitWaiting = false;
-          hasInitDone = true;
-
-          if (colors == null || colors.Length != webCamTexture.width * webCamTexture.height) // 确定color尺寸
-          {
-            colors = new Color32[webCamTexture.width * webCamTexture.height];
-          }
-          if (orginalPreviewTexture2D == null || orginalPreviewTexture2D.width != webCamTexture.width || orginalPreviewTexture2D.height != webCamTexture.height) // 确定texture2d尺寸
-          {
-            orginalPreviewTexture2D = new Texture2D(webCamTexture.width, webCamTexture.height, TextureFormat.RGBA32, false);
-          }
-
-          rgbaMat = new Mat(webCamTexture.height, webCamTexture.width, CvType.CV_8UC4, new Scalar(0, 0, 0, 255)); // 高、宽
-
-          // UpdatePreview();
-          break;
-        }
-        else
-        {
-          yield return null;
-        }
-      }
-      yield break;
-    }
-
-    // ==================================================
-    // 释放资源
-    // DONE
-    private void Dispose()
-    {
-      isInitWaiting = false;
-      hasInitDone = false;
-
-      if (webCamTexture != null)
-      {
-        webCamTexture.Stop();
-        Destroy(webCamTexture);
-        webCamTexture = null;
-      }
-      if (rgbaMat != null)
-      {
-        rgbaMat.Dispose();
-        rgbaMat = null;
-      }
-      if (orginalPreviewTexture2D != null)
-      {
-        Destroy(orginalPreviewTexture2D);
-        orginalPreviewTexture2D = null;
-      }
-      return;
-    }
-
-    // ==================================================
-    // 按钮
-
-    public void OnPlayButtonClick()
-    {
-      if (hasInitDone)
-      {
-        webCamTexture.Play();
-      }
-      return;
-    }
-
-    public void OnPauseButtonClick()
-    {
-      if (hasInitDone)
-      {
-        webCamTexture.Pause();
-      }
-      return;
-    }
-
-    public void OnStopButtonClick()
-    {
-      if (hasInitDone)
-      {
-        webCamTexture.Stop();
-      }
-      return;
-    }
-
-    // ==================================================
-    // 相机配置
-    // DONE
-    private string requestedDeviceName = "Logitech BRIO";
-    // private string requestedDeviceName = "GC21 Video";
-    private int requestedWidth = 440;
-    private int requestedHeight = 440;
-    private int requestedFPS = 30;
-    private void CreateCamera()
-    {
-      foreach (WebCamDevice device in WebCamTexture.devices)
-      {
-        if (device.name == requestedDeviceName)
-        {
-          webCamDevice = device;
-          webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
-          webCamTexture.Play();
-        }
-      }
-      return;
-    }
-
-    // ==================================================
-    // 预览画面
-
-    public Image ImageOrginalPreview;
-    private Texture2D orginalPreviewTexture2D;
-    private void UpdatePreview()
-    {
-      if (!ImageOrginalPreview)
-      {
-        return;
-      }
-
-      Utils.matToTexture2D(rgbaMat, orginalPreviewTexture2D, colors); // Mat更新为texture2d
-
-      // texture2D = RotateTexutre(texture2D, false);
-      ImageOrginalPreview.sprite = Sprite.Create(orginalPreviewTexture2D, new UnityEngine.Rect(0, 0, orginalPreviewTexture2D.width, orginalPreviewTexture2D.height), Vector2.zero);
-      return;
-    }
-
-    // ==================================================
-    //  Texture画面旋转
-    // private Texture2D RotateTexutre(Texture2D originalTexture, bool clockwise)
-    // {
-    //   Color32[] original = originalTexture.GetPixels32();
-    //   Color32[] rotated = new Color32[original.Length];
-    //   int w = originalTexture.width;
-    //   int h = originalTexture.height;
-
-    //   int iRotated, iOriginal;
-
-    //   for (int j = 0; j < h; ++j)
-    //   {
-    //     for (int i = 0; i < w; ++i)
-    //     {
-    //       iRotated = (i + 1) * h - j - 1;
-    //       iOriginal = clockwise ? original.Length - 1 - (j * w + i) : j * w + i;
-    //       rotated[iRotated] = original[iOriginal];
-    //     }
-    //   }
-
-    //   Texture2D newTexture = new Texture2D(originalTexture.height, originalTexture.width, TextureFormat.RGBA32, false);
-    //   newTexture.SetPixels32(rotated);
-    //   newTexture.Apply();
-    //   return newTexture;
-    // }
-  }
-}