using System;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using OpenCVForUnity.CoreModule;
using OpenCVForUnity.UnityUtils;
using OpenCVForUnity.ImgprocModule;
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;
// Creates the camera
if (!String.IsNullOrEmpty (requestedDeviceName)) {
int requestedDeviceIndex = -1;
if (Int32.TryParse (requestedDeviceName, out requestedDeviceIndex)) {
if (requestedDeviceIndex >= 0 && requestedDeviceIndex < WebCamTexture.devices.Length) {
webCamDevice = WebCamTexture.devices [requestedDeviceIndex];
webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
}
} else {
for (int cameraIndex = 0; cameraIndex < WebCamTexture.devices.Length; cameraIndex++) {
if (WebCamTexture.devices [cameraIndex].name == requestedDeviceName) {
webCamDevice = WebCamTexture.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 < WebCamTexture.devices.Length; cameraIndex++) {
if (WebCamTexture.devices [cameraIndex].isFrontFacing == requestedIsFrontFacing) {
webCamDevice = WebCamTexture.devices [cameraIndex];
webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
break;
}
}
}
if (webCamTexture == null) {
if (WebCamTexture.devices.Length > 0) {
webCamDevice = WebCamTexture.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 you want to use webcamTexture.width and webcamTexture.height on iOS, you have to wait until webcamTexture.didUpdateThisFrame == 1, otherwise these two values will be equal to 16. (http://forum.unity3d.com/threads/webcamtexture-and-error-0x0502.123922/).
#if UNITY_IOS && !UNITY_EDITOR && (UNITY_4_6_3 || UNITY_4_6_4 || UNITY_5_0_0 || UNITY_5_0_1)
if (webCamTexture.width > 16 && webCamTexture.height > 16) {
#else
if (webCamTexture.didUpdateThisFrame) {
#if UNITY_IOS && !UNITY_EDITOR && UNITY_5_2
while (webCamTexture.width <= 16) {
webCamTexture.GetPixels32 ();
yield return new WaitForEndOfFrame ();
}
#endif
#endif
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;
}
}
}
///
/// 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);
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 ();
}
}
}
}