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(); } } } }