FaceDetecter.cs 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. // using OpenCVSharp;
  6. using OpenCVForUnity;
  7. using OpenCVForUnity.CoreModule;
  8. using OpenCVForUnity.ImgprocModule;
  9. using OpenCVForUnity.UnityUtils;
  10. using OpenCVForUnity.ObjdetectModule;
  11. namespace DiageoWhiskyBlending
  12. {
  13. public class FaceDetecter : MonoBehaviour
  14. {
  15. private Mat gray; // 灰度图,方便识别
  16. private Mat rotatedNewMat;
  17. private MatOfRect faceRect; // 识别到的人脸的区域
  18. private CascadeClassifier classifier; // 人脸识别分类器
  19. private string cascadePath;
  20. public float index = 0;
  21. // ==================================================
  22. private void Start()
  23. {
  24. // LogAllWebCam();
  25. Init();
  26. }
  27. private void OnDestroy()
  28. {
  29. Dispose();
  30. }
  31. private void OnApplicationQuit()
  32. {
  33. Dispose();
  34. }
  35. // ==================================================
  36. private void Init()
  37. {
  38. cascadePath = Application.streamingAssetsPath + "/haarcascade_frontalface_alt2.xml";
  39. gray = new Mat(); // 初始化Mat
  40. faceRect = new MatOfRect(); // 初始化识别到的人脸的区域
  41. classifier = new CascadeClassifier(cascadePath); // 初始化人脸识别分类器
  42. previewMat = new Mat();
  43. previewTexture2D = new Texture2D(440, 440, TextureFormat.RGBA32, false);
  44. return;
  45. }
  46. private void Dispose()
  47. {
  48. if (rotatedNewMat != null)
  49. {
  50. rotatedNewMat.Dispose();
  51. rotatedNewMat = null;
  52. }
  53. if (previewMat != null)
  54. {
  55. previewMat.Dispose();
  56. previewMat = null;
  57. }
  58. if (previewTexture2D != null)
  59. {
  60. Destroy(previewTexture2D);
  61. previewTexture2D = null;
  62. }
  63. return;
  64. }
  65. public void DetectFace(Mat rgbaMat)
  66. {
  67. rotatedNewMat = MatRotate(rgbaMat.clone()); // 旋转原数据
  68. Imgproc.cvtColor(rotatedNewMat, gray, Imgproc.COLOR_RGBA2GRAY); // 将获取到的摄像头画面转化为灰度图并赋值给gray
  69. // mat/面部矩形向量组/识别精度越高越快越不准/面部识别次数2次以上算识别/?性能优化/最小检测尺寸/最大检测尺寸
  70. classifier.detectMultiScale(gray, faceRect, 1.1d, 2, 2, new Size(20, 20), new Size()); // 检测gray中的人脸
  71. OpenCVForUnity.CoreModule.Rect[] rects = faceRect.toArray();
  72. if (rects.Length > 0)
  73. {
  74. for (int i = 0; i < rects.Length; i++)
  75. {
  76. 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即为框的宽和高
  77. }
  78. index += Time.deltaTime;
  79. if (index > .3f)
  80. {
  81. Debug.Log("连续监测超过1s...[OK]");
  82. GameManager.Instance.EnterLogicScene00();
  83. }
  84. }
  85. else
  86. {
  87. // if (index > 0)
  88. // {
  89. // index -= Time.deltaTime / 2;
  90. // if (index < 0)
  91. // {
  92. index = 0;
  93. // }
  94. // }
  95. }
  96. // 深复制识别、画框数据并显示
  97. UpdatePreview(rotatedNewMat);
  98. return;
  99. }
  100. // ==================================================
  101. // 预览画面
  102. public Image ImagePreviewImage;
  103. private Mat previewMat;
  104. private Texture2D previewTexture2D;
  105. private void UpdatePreview(Mat value)
  106. {
  107. if (!ImagePreviewImage)
  108. {
  109. return;
  110. }
  111. previewMat = value.clone();
  112. Utils.matToTexture2D(previewMat, previewTexture2D);
  113. ImagePreviewImage.sprite = Sprite.Create(previewTexture2D, new UnityEngine.Rect(0, 0, 440, 440), Vector2.zero);
  114. return;
  115. }
  116. // ==================================================
  117. /// <summary>
  118. /// Mat旋转方法
  119. /// </summary>
  120. /// <param name="orginalMat"></param>
  121. /// <returns></returns>
  122. private Mat MatRotate(Mat orginalMat)
  123. {
  124. Mat rotatedMat = new Mat(orginalMat.height(), orginalMat.width(), CvType.CV_8UC4, new Scalar(0, 0, 0, 255)); // DEBUG:宽高可能相反
  125. // mat旋转
  126. Point center = new Point(orginalMat.cols() / 2f, orginalMat.rows() / 2f);
  127. Mat mat = Imgproc.getRotationMatrix2D(center, 90, 1);
  128. Imgproc.warpAffine(orginalMat, rotatedMat, mat, orginalMat.size());
  129. return rotatedMat;
  130. }
  131. /// <summary>
  132. /// 预览有多少相机
  133. /// </summary>
  134. private void LogAllWebCam()
  135. {
  136. Debug.Log($"Found {WebCamTexture.devices.Length} device...<color=green>[OK]</color>");
  137. foreach (WebCamDevice webcamDevice in WebCamTexture.devices)
  138. {
  139. Debug.Log($"{webcamDevice.name}...<color=green>[OK]</color>");
  140. }
  141. return;
  142. }
  143. }
  144. }