using OpenCVForUnity;
using OpenCVForUnity.CoreModule;
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.UnityUtils;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
///
/// WebCam色彩图处理
///
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().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 = 480; // 440
private int requestedHeight = 270; // 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 预览画面
private bool allowPreview = false;
public void SwitchPreview(bool value)
{
allowPreview = value;
return;
}
[SerializeField] private Image originalPreviewImage;
private Texture2D orginalPreviewTexture2D;
private void UpdateOriginalPreview()
{
if (!allowPreview)
{
return;
}
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;
// }
}