using OpenCVForUnity.CoreModule;
using OpenCVForUnity.ImgprocModule;
using OpenCVForUnity.UnityUtils;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace OpenCVForUnityExample
{
///
/// WebCamTextureToMat Example
/// An example of converting a WebCamTexture image to OpenCV's Mat format.
///
public class WebCamTextureToMatExample : MonoBehaviour
{
///
/// Set the name of the device to use.
///
[SerializeField, TooltipAttribute("Set the name of the device to use.")]
public string requestedDeviceName = null;
///
/// Set the width of WebCamTexture.
///
[SerializeField, TooltipAttribute("Set the width of WebCamTexture.")]
public int requestedWidth = 640;
///
/// Set the height of WebCamTexture.
///
[SerializeField, TooltipAttribute("Set the height of WebCamTexture.")]
public int requestedHeight = 480;
///
/// Set FPS of WebCamTexture.
///
[SerializeField, TooltipAttribute("Set FPS of WebCamTexture.")]
public int requestedFPS = 30;
///
/// Set whether to use the front facing camera.
///
[SerializeField, TooltipAttribute("Set whether to use the front facing camera.")]
public bool requestedIsFrontFacing = false;
///
/// The webcam texture.
///
WebCamTexture webCamTexture;
///
/// The webcam device.
///
WebCamDevice webCamDevice;
///
/// The rgba mat.
///
Mat rgbaMat;
///
/// The colors.
///
Color32[] colors;
///
/// The texture.
///
Texture2D texture;
///
/// Indicates whether this instance is waiting for initialization to complete.
///
bool isInitWaiting = false;
///
/// Indicates whether this instance has been initialized.
///
bool hasInitDone = false;
///
/// The FPS monitor.
///
FpsMonitor fpsMonitor;
// Use this for initialization
void Start()
{
fpsMonitor = GetComponent();
Initialize();
}
///
/// Initializes webcam texture.
///
private void Initialize()
{
if (isInitWaiting)
return;
#if UNITY_ANDROID && !UNITY_EDITOR
// Set the requestedFPS parameter to avoid the problem of the WebCamTexture image becoming low light on some Android devices (e.g. Google Pixel, Pixel2).
// https://forum.unity.com/threads/android-webcamtexture-in-low-light-only-some-models.520656/
// https://forum.unity.com/threads/released-opencv-for-unity.277080/page-33#post-3445178
if (requestedIsFrontFacing)
{
int rearCameraFPS = requestedFPS;
requestedFPS = 15;
StartCoroutine(_Initialize());
requestedFPS = rearCameraFPS;
}
else
{
StartCoroutine(_Initialize());
}
#else
StartCoroutine(_Initialize());
#endif
}
///
/// Initializes webcam texture by coroutine.
///
private IEnumerator _Initialize()
{
if (hasInitDone)
Dispose();
isInitWaiting = true;
// Checks camera permission state.
#if (UNITY_IOS || UNITY_WEBGL) && UNITY_2018_1_OR_NEWER
UserAuthorization mode = UserAuthorization.WebCam;
if (!Application.HasUserAuthorization(mode))
{
isUserRequestingPermission = true;
yield return Application.RequestUserAuthorization(mode);
float timeElapsed = 0;
while (isUserRequestingPermission)
{
if (timeElapsed > 0.25f)
{
isUserRequestingPermission = false;
break;
}
timeElapsed += Time.deltaTime;
yield return null;
}
}
if (!Application.HasUserAuthorization(mode))
{
if (fpsMonitor != null)
{
fpsMonitor.consoleText = "Camera permission is denied.";
}
isInitWaiting = false;
yield break;
}
#elif UNITY_ANDROID && UNITY_2018_3_OR_NEWER
string permission = UnityEngine.Android.Permission.Camera;
if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission))
{
isUserRequestingPermission = true;
UnityEngine.Android.Permission.RequestUserPermission(permission);
float timeElapsed = 0;
while (isUserRequestingPermission)
{
if (timeElapsed > 0.25f)
{
isUserRequestingPermission = false;
break;
}
timeElapsed += Time.deltaTime;
yield return null;
}
}
if (!UnityEngine.Android.Permission.HasUserAuthorizedPermission(permission))
{
if (fpsMonitor != null)
{
fpsMonitor.consoleText = "Camera permission is denied.";
}
isInitWaiting = false;
yield break;
}
#endif
// Creates the camera
var devices = WebCamTexture.devices;
if (!String.IsNullOrEmpty(requestedDeviceName))
{
int requestedDeviceIndex = -1;
if (Int32.TryParse(requestedDeviceName, out requestedDeviceIndex))
{
if (requestedDeviceIndex >= 0 && requestedDeviceIndex < devices.Length)
{
webCamDevice = devices[requestedDeviceIndex];
webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
}
}
else
{
for (int cameraIndex = 0; cameraIndex < devices.Length; cameraIndex++)
{
if (devices[cameraIndex].name == requestedDeviceName)
{
webCamDevice = devices[cameraIndex];
webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
break;
}
}
}
if (webCamTexture == null)
Debug.Log("Cannot find camera device " + requestedDeviceName + ".");
}
if (webCamTexture == null)
{
// Checks how many and which cameras are available on the device
for (int cameraIndex = 0; cameraIndex < devices.Length; cameraIndex++)
{
#if UNITY_2018_3_OR_NEWER
if (devices[cameraIndex].kind != WebCamKind.ColorAndDepth && devices[cameraIndex].isFrontFacing == requestedIsFrontFacing)
#else
if (devices[cameraIndex].isFrontFacing == requestedIsFrontFacing)
#endif
{
webCamDevice = devices[cameraIndex];
webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
break;
}
}
}
if (webCamTexture == null)
{
if (devices.Length > 0)
{
webCamDevice = devices[0];
webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
}
else
{
Debug.LogError("Camera device does not exist.");
isInitWaiting = false;
yield break;
}
}
// Starts the camera.
webCamTexture.Play();
while (true)
{
if (webCamTexture.didUpdateThisFrame)
{
Debug.Log("name:" + webCamTexture.deviceName + " width:" + webCamTexture.width + " height:" + webCamTexture.height + " fps:" + webCamTexture.requestedFPS);
Debug.Log("videoRotationAngle:" + webCamTexture.videoRotationAngle + " videoVerticallyMirrored:" + webCamTexture.videoVerticallyMirrored + " isFrongFacing:" + webCamDevice.isFrontFacing);
isInitWaiting = false;
hasInitDone = true;
OnInited();
break;
}
else
{
yield return null;
}
}
}
#if ((UNITY_IOS || UNITY_WEBGL) && UNITY_2018_1_OR_NEWER) || (UNITY_ANDROID && UNITY_2018_3_OR_NEWER)
bool isUserRequestingPermission;
IEnumerator OnApplicationFocus(bool hasFocus)
{
yield return null;
if (isUserRequestingPermission && hasFocus)
isUserRequestingPermission = false;
}
#endif
///
/// Releases all resource.
///
private void Dispose()
{
isInitWaiting = false;
hasInitDone = false;
if (webCamTexture != null)
{
webCamTexture.Stop();
WebCamTexture.Destroy(webCamTexture);
webCamTexture = null;
}
if (rgbaMat != null)
{
rgbaMat.Dispose();
rgbaMat = null;
}
if (texture != null)
{
Texture2D.Destroy(texture);
texture = null;
}
}
///
/// Raises the webcam texture initialized event.
///
private void OnInited()
{
if (colors == null || colors.Length != webCamTexture.width * webCamTexture.height)
colors = new Color32[webCamTexture.width * webCamTexture.height];
if (texture == null || texture.width != webCamTexture.width || texture.height != webCamTexture.height)
texture = 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));
Utils.matToTexture2D(rgbaMat, texture, colors);
gameObject.GetComponent().material.mainTexture = texture;
gameObject.transform.localScale = new Vector3(webCamTexture.width, webCamTexture.height, 1);
Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
if (fpsMonitor != null)
{
fpsMonitor.Add("width", rgbaMat.width().ToString());
fpsMonitor.Add("height", rgbaMat.height().ToString());
fpsMonitor.Add("orientation", Screen.orientation.ToString());
}
float width = rgbaMat.width();
float height = rgbaMat.height();
float widthScale = (float)Screen.width / width;
float heightScale = (float)Screen.height / height;
if (widthScale < heightScale)
{
Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
}
else
{
Camera.main.orthographicSize = height / 2;
}
}
// Update is called once per frame
void Update()
{
if (hasInitDone && webCamTexture.isPlaying && webCamTexture.didUpdateThisFrame)
{
Utils.webCamTextureToMat(webCamTexture, rgbaMat, colors);
//Imgproc.putText (rgbaMat, "W:" + rgbaMat.width () + " H:" + rgbaMat.height () + " SO:" + Screen.orientation, new Point (5, rgbaMat.rows () - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar (255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
Utils.matToTexture2D(rgbaMat, texture, colors);
}
}
///
/// Raises the destroy event.
///
void OnDestroy()
{
Dispose();
}
///
/// Raises the back button click event.
///
public void OnBackButtonClick()
{
SceneManager.LoadScene("OpenCVForUnityExample");
}
///
/// Raises the play button click event.
///
public void OnPlayButtonClick()
{
if (hasInitDone)
webCamTexture.Play();
}
///
/// Raises the pause button click event.
///
public void OnPauseButtonClick()
{
if (hasInitDone)
webCamTexture.Pause();
}
///
/// Raises the stop button click event.
///
public void OnStopButtonClick()
{
if (hasInitDone)
webCamTexture.Stop();
}
///
/// Raises the change camera button click event.
///
public void OnChangeCameraButtonClick()
{
if (hasInitDone)
{
requestedDeviceName = null;
requestedIsFrontFacing = !requestedIsFrontFacing;
Initialize();
}
}
}
}