using System; using UnityEngine; using UI = UnityEngine.UI; using Klak.TestTools; using System.Linq; using System.Collections.Generic; using Zenject; namespace UltraFace { public sealed class Visualizer : MonoBehaviour { #region Editable attributes [SerializeField] ImageSource _source = null; [SerializeField, Range(0, 1)] float _threshold = 0.5f; [SerializeField] ResourceSet _resources = null; [SerializeField] Shader _visualizer = null; [SerializeField] Texture2D _texture = null; [SerializeField] UI.RawImage _previewUI = null; [Inject] private DetectionSetup _detectionSetup; public int faceCounter => _detector.Detections.Count(); public float minFaceHeight { get { if(_detector.Detections.Count() == 0) return 0f; else return _detector.Detections.Min(face => face.y2 - face.y1); } } public float maxFaceHeight { get { if(_detector.Detections.Count() == 0) return 0f; else return _detector.Detections.Max(face => face.y2 - face.y1); } } public Action OnDetectionStatusChanged; private List _detectedCounter; private bool _isDetected; #endregion #region Private objects FaceDetector _detector; Material _material; ComputeBuffer _drawArgs; #endregion #region MonoBehaviour implementation void Start() { _detector = new FaceDetector(_resources); _material = new Material(_visualizer); _drawArgs = new ComputeBuffer(4, sizeof(uint), ComputeBufferType.IndirectArguments); _drawArgs.SetData(new [] {6, 0, 0, 0}); _detectedCounter = new List(); } public void Init() { OnDetectionStatusChanged?.Invoke(false); } void Update() { _detector.ProcessImage(_source.Texture, _threshold); _previewUI.texture = _source.Texture; if(!_detectionSetup.isValidate) return; Debug.Log(_detectedCounter.Count); _detectedCounter.Add(maxFaceHeight > _detectionSetup.minFaceHeight ? true : false); if(_detectedCounter.Count == 128) { var trueCounter = _detectedCounter.Count(x => x == true); if(!_isDetected && trueCounter >= 64) { if(maxFaceHeight < _detectionSetup.minFaceHeight) return; _isDetected = true; Debug.LogWarning("лицо определено"); } else if(_isDetected && trueCounter < 64) { _isDetected = false; Debug.LogWarning("лицо потеряно"); } OnDetectionStatusChanged?.Invoke(_isDetected); _detectedCounter = new List(); } } void OnRenderObject() { return; _detector.SetIndirectDrawCount(_drawArgs); _material.SetFloat("_Threshold", _threshold); _material.SetTexture("_Texture", _texture); _material.SetBuffer("_Detections", _detector.DetectionBuffer); _material.SetPass(_texture == null ? 0 : 1); Graphics.DrawProceduralIndirectNow(MeshTopology.Triangles, _drawArgs, 0); } void OnDestroy() { _detector?.Dispose(); Destroy(_material); _drawArgs?.Dispose(); } #endregion } }