Advertisement
Guest User

WebCamTextureToMatHelper

a guest
Nov 12th, 2019
256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 36.73 KB | None | 0 0
  1. #if !(UNITY_LUMIN && !UNITY_EDITOR)
  2.  
  3. using System;
  4. using System.Collections;
  5. using UnityEngine;
  6. using UnityEngine.Events;
  7. using UnityEngine.Serialization;
  8. using OpenCVForUnity.CoreModule;
  9. using OpenCVForUnity.UnityUtils;
  10.  
  11. namespace OpenCVForUnity.UnityUtils.Helper
  12. {
  13.     /// <summary>
  14.     /// WebcamTexture to mat helper.
  15.     /// v 1.1.0
  16.     /// </summary>
  17.     public class WebCamTextureToMatHelper : MonoBehaviour
  18.     {
  19.         /// <summary>
  20.         /// Set the name of the camera device to use. (or device index number)
  21.         /// </summary>
  22.         [SerializeField, FormerlySerializedAs("requestedDeviceName"), TooltipAttribute("Set the name of the device to use. (or device index number)")]
  23.         protected string _requestedDeviceName = null;
  24.  
  25.         public virtual string requestedDeviceName
  26.         {
  27.             get { return _requestedDeviceName; }
  28.             set
  29.             {
  30.                 _requestedDeviceName = value;
  31.                 if (hasInitDone)
  32.                 {
  33.                     Initialize();
  34.                 }
  35.             }
  36.         }
  37.  
  38.         /// <summary>
  39.         /// Set the width of camera.
  40.         /// </summary>
  41.         [SerializeField, FormerlySerializedAs("requestedWidth"), TooltipAttribute("Set the width of camera.")]
  42.         protected int _requestedWidth = 640;
  43.  
  44.         public virtual int requestedWidth
  45.         {
  46.             get { return _requestedWidth; }
  47.             set
  48.             {
  49.                 _requestedWidth = (int)Mathf.Clamp(value, 0f, float.MaxValue);
  50.                 if (hasInitDone)
  51.                 {
  52.                     Initialize();
  53.                 }
  54.             }
  55.         }
  56.  
  57.         /// <summary>
  58.         /// Set the height of camera.
  59.         /// </summary>
  60.         [SerializeField, FormerlySerializedAs("requestedHeight"), TooltipAttribute("Set the height of camera.")]
  61.         protected int _requestedHeight = 480;
  62.  
  63.         public virtual int requestedHeight
  64.         {
  65.             get { return _requestedHeight; }
  66.             set
  67.             {
  68.                 _requestedHeight = (int)Mathf.Clamp(value, 0f, float.MaxValue);
  69.                 if (hasInitDone)
  70.                 {
  71.                     Initialize();
  72.                 }
  73.             }
  74.         }
  75.  
  76.         /// <summary>
  77.         /// Set whether to use the front facing camera.
  78.         /// </summary>
  79.         [SerializeField, FormerlySerializedAs("requestedIsFrontFacing"), TooltipAttribute("Set whether to use the front facing camera.")]
  80.         protected bool _requestedIsFrontFacing = false;
  81.  
  82.         public virtual bool requestedIsFrontFacing
  83.         {
  84.             get { return _requestedIsFrontFacing; }
  85.             set
  86.             {
  87.                 _requestedIsFrontFacing = value;
  88.                 if (hasInitDone)
  89.                 {
  90.                     Initialize(_requestedIsFrontFacing, requestedFPS, rotate90Degree);
  91.                 }
  92.             }
  93.         }
  94.  
  95.         /// <summary>
  96.         /// Set the frame rate of camera.
  97.         /// </summary>
  98.         [SerializeField, FormerlySerializedAs("requestedFPS"), TooltipAttribute("Set the frame rate of camera.")]
  99.         protected float _requestedFPS = 30f;
  100.  
  101.         public virtual float requestedFPS
  102.         {
  103.             get { return _requestedFPS; }
  104.             set
  105.             {
  106.                 _requestedFPS = Mathf.Clamp(value, -1f, float.MaxValue);
  107.                 if (hasInitDone)
  108.                 {
  109.                     bool isPlaying = IsPlaying();
  110.                     Stop();
  111.                     webCamTexture.requestedFPS = _requestedFPS;
  112.                     if (isPlaying)
  113.                         Play();
  114.                 }
  115.             }
  116.         }
  117.  
  118.         /// <summary>
  119.         /// Sets whether to rotate camera frame 90 degrees. (clockwise)
  120.         /// </summary>
  121.         [SerializeField, FormerlySerializedAs("rotate90Degree"), TooltipAttribute("Sets whether to rotate camera frame 90 degrees. (clockwise)")]
  122.         protected bool _rotate90Degree = false;
  123.  
  124.         public virtual bool rotate90Degree
  125.         {
  126.             get { return _rotate90Degree; }
  127.             set
  128.             {
  129.                 _rotate90Degree = value;
  130.                 if (hasInitDone)
  131.                 {
  132.                     Initialize();
  133.                 }
  134.             }
  135.         }
  136.  
  137.         /// <summary>
  138.         /// Determines if flips vertically.
  139.         /// </summary>
  140.         [SerializeField, FormerlySerializedAs("flipVertical"), TooltipAttribute("Determines if flips vertically.")]
  141.         protected bool _flipVertical = false;
  142.  
  143.         public virtual bool flipVertical
  144.         {
  145.             get { return _flipVertical; }
  146.             set { _flipVertical = value; }
  147.         }
  148.  
  149.         /// <summary>
  150.         /// Determines if flips horizontal.
  151.         /// </summary>
  152.         [SerializeField, FormerlySerializedAs("flipHorizontal"), TooltipAttribute("Determines if flips horizontal.")]
  153.         protected bool _flipHorizontal = false;
  154.  
  155.         public virtual bool flipHorizontal
  156.         {
  157.             get { return _flipHorizontal; }
  158.             set { _flipHorizontal = value; }
  159.         }
  160.  
  161.         /// <summary>
  162.         /// The number of frames before the initialization process times out.
  163.         /// </summary>
  164.         [SerializeField, FormerlySerializedAs("timeoutFrameCount"), TooltipAttribute("The number of frames before the initialization process times out.")]
  165.         protected int _timeoutFrameCount = 300;
  166.  
  167.         public virtual int timeoutFrameCount
  168.         {
  169.             get { return _timeoutFrameCount; }
  170.             set { _timeoutFrameCount = (int)Mathf.Clamp(value, 0f, float.MaxValue); }
  171.         }
  172.  
  173.         /// <summary>
  174.         /// UnityEvent that is triggered when this instance is initialized.
  175.         /// </summary>
  176.         public UnityEvent onInitialized;
  177.  
  178.         /// <summary>
  179.         /// UnityEvent that is triggered when this instance is disposed.
  180.         /// </summary>
  181.         public UnityEvent onDisposed;
  182.  
  183.         /// <summary>
  184.         /// UnityEvent that is triggered when this instance is error Occurred.
  185.         /// </summary>
  186.         public ErrorUnityEvent onErrorOccurred;
  187.  
  188.         /// <summary>
  189.         /// The active WebcamTexture.
  190.         /// </summary>
  191.         protected WebCamTexture webCamTexture;
  192.  
  193.         /// <summary>
  194.         /// The active WebcamDevice.
  195.         /// </summary>
  196.         protected WebCamDevice webCamDevice;
  197.  
  198.         /// <summary>
  199.         /// The frame mat.
  200.         /// </summary>
  201.         protected Mat frameMat;
  202.  
  203.         /// <summary>
  204.         /// The rotated frame mat
  205.         /// </summary>
  206.         protected Mat rotatedFrameMat;
  207.  
  208.         /// <summary>
  209.         /// The buffer colors.
  210.         /// </summary>
  211.         protected Color32[] colors;
  212.  
  213.         /// <summary>
  214.         /// Indicates whether this instance is waiting for initialization to complete.
  215.         /// </summary>
  216.         protected bool isInitWaiting = false;
  217.  
  218.         /// <summary>
  219.         /// Indicates whether this instance has been initialized.
  220.         /// </summary>
  221.         protected bool hasInitDone = false;
  222.  
  223.         /// <summary>
  224.         /// The initialization coroutine.
  225.         /// </summary>
  226.         protected IEnumerator initCoroutine;
  227.  
  228.         /// <summary>
  229.         /// The orientation of the screen.
  230.         /// </summary>
  231.         protected ScreenOrientation screenOrientation;
  232.  
  233.         /// <summary>
  234.         /// The width of the screen.
  235.         /// </summary>
  236.         protected int screenWidth;
  237.  
  238.         /// <summary>
  239.         /// The height of the screen.
  240.         /// </summary>
  241.         protected int screenHeight;
  242.  
  243.         /// <summary>
  244.         /// Indicates whether this instance avoids the front camera low light issue that occurs in only some Android devices (e.g. Google Pixel, Pixel2).
  245.         /// Sets compulsorily the requestedFPS parameter to 15 (only when using the front camera), to avoid the problem of the WebCamTexture image becoming low light.
  246.         /// https://forum.unity.com/threads/android-webcamtexture-in-low-light-only-some-models.520656/
  247.         /// https://forum.unity.com/threads/released-opencv-for-unity.277080/page-33#post-3445178
  248.         /// </summary>
  249.         public bool avoidAndroidFrontCameraLowLightIssue = false;
  250.  
  251.         [System.Serializable]
  252.         public enum ErrorCode : int
  253.         {
  254.             UNKNOWN = 0,
  255.             CAMERA_DEVICE_NOT_EXIST = 1,
  256.             TIMEOUT = 2,
  257.         }
  258.  
  259.         [System.Serializable]
  260.         public class ErrorUnityEvent : UnityEngine.Events.UnityEvent<ErrorCode>
  261.         {
  262.  
  263.         }
  264.  
  265.         protected virtual void OnValidate()
  266.         {
  267.             _requestedWidth = (int)Mathf.Clamp(_requestedWidth, 0f, float.MaxValue);
  268.             _requestedHeight = (int)Mathf.Clamp(_requestedHeight, 0f, float.MaxValue);
  269.             _requestedFPS = Mathf.Clamp(_requestedFPS, -1f, float.MaxValue);
  270.             _timeoutFrameCount = (int)Mathf.Clamp(_timeoutFrameCount, 0f, float.MaxValue);
  271.         }
  272.  
  273.         // Update is called once per frame
  274.         protected virtual void Update()
  275.         {
  276.             if (hasInitDone)
  277.             {
  278.                 // Catch the orientation change of the screen and correct the mat image to the correct direction.
  279.                 if (screenOrientation != Screen.orientation && (screenWidth != Screen.width || screenHeight != Screen.height))
  280.                 {
  281.  
  282.                     if (onDisposed != null)
  283.                         onDisposed.Invoke();
  284.  
  285.                     if (frameMat != null)
  286.                     {
  287.                         frameMat.Dispose();
  288.                         frameMat = null;
  289.                     }
  290.                     if (rotatedFrameMat != null)
  291.                     {
  292.                         rotatedFrameMat.Dispose();
  293.                         rotatedFrameMat = null;
  294.                     }
  295.  
  296.                     frameMat = new Mat(webCamTexture.height, webCamTexture.width, CvType.CV_8UC4, new Scalar(0, 0, 0, 255));
  297.                     screenOrientation = Screen.orientation;
  298.                     screenWidth = Screen.width;
  299.                     screenHeight = Screen.height;
  300.  
  301.                     bool isRotatedFrame = false;
  302. #if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
  303.                     if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown)
  304.                     {
  305.                         if (!rotate90Degree)
  306.                             isRotatedFrame = true;
  307.                     }
  308.                     else if (rotate90Degree)
  309.                     {
  310.                         isRotatedFrame = true;
  311.                     }
  312. #else
  313.                     if (rotate90Degree)
  314.                         isRotatedFrame = true;
  315. #endif
  316.                     if (isRotatedFrame)
  317.                         rotatedFrameMat = new Mat(webCamTexture.width, webCamTexture.height, CvType.CV_8UC4, new Scalar(0, 0, 0, 255));
  318.  
  319.                     if (onInitialized != null)
  320.                         onInitialized.Invoke();
  321.                 }
  322.                 else
  323.                 {
  324.                     screenWidth = Screen.width;
  325.                     screenHeight = Screen.height;
  326.                 }
  327.             }
  328.         }
  329.  
  330.         /// <summary>
  331.         /// Raises the destroy event.
  332.         /// </summary>
  333.         protected virtual void OnDestroy()
  334.         {
  335.             Dispose();
  336.         }
  337.  
  338.         /// <summary>
  339.         /// Initializes this instance.
  340.         /// </summary>
  341.         public virtual void Initialize()
  342.         {
  343.             if (isInitWaiting)
  344.             {
  345.                 CancelInitCoroutine();
  346.                 ReleaseResources();
  347.             }
  348.  
  349.             if (onInitialized == null)
  350.                 onInitialized = new UnityEvent();
  351.             if (onDisposed == null)
  352.                 onDisposed = new UnityEvent();
  353.             if (onErrorOccurred == null)
  354.                 onErrorOccurred = new ErrorUnityEvent();
  355.  
  356.             initCoroutine = _Initialize();
  357.             StartCoroutine(initCoroutine);
  358.         }
  359.  
  360.         /// <summary>
  361.         /// Initializes this instance.
  362.         /// </summary>
  363.         /// <param name="requestedWidth">Requested width.</param>
  364.         /// <param name="requestedHeight">Requested height.</param>
  365.         public virtual void Initialize(int requestedWidth, int requestedHeight)
  366.         {
  367.             if (isInitWaiting)
  368.             {
  369.                 CancelInitCoroutine();
  370.                 ReleaseResources();
  371.             }
  372.  
  373.             this._requestedWidth = requestedWidth;
  374.             this._requestedHeight = requestedHeight;
  375.             if (onInitialized == null)
  376.                 onInitialized = new UnityEvent();
  377.             if (onDisposed == null)
  378.                 onDisposed = new UnityEvent();
  379.             if (onErrorOccurred == null)
  380.                 onErrorOccurred = new ErrorUnityEvent();
  381.  
  382.             initCoroutine = _Initialize();
  383.             StartCoroutine(initCoroutine);
  384.         }
  385.  
  386.         /// <summary>
  387.         /// Initializes this instance.
  388.         /// </summary>
  389.         /// <param name="requestedIsFrontFacing">If set to <c>true</c> requested to using the front camera.</param>
  390.         /// <param name="requestedFPS">Requested FPS.</param>
  391.         /// <param name="rotate90Degree">If set to <c>true</c> requested to rotate camera frame 90 degrees. (clockwise)</param>
  392.         public virtual void Initialize(bool requestedIsFrontFacing, float requestedFPS = 30f, bool rotate90Degree = false)
  393.         {
  394.             if (isInitWaiting)
  395.             {
  396.                 CancelInitCoroutine();
  397.                 ReleaseResources();
  398.             }
  399.  
  400.             _requestedDeviceName = null;
  401.             this._requestedIsFrontFacing = requestedIsFrontFacing;
  402.             this._requestedFPS = requestedFPS;
  403.             this._rotate90Degree = rotate90Degree;
  404.             if (onInitialized == null)
  405.                 onInitialized = new UnityEvent();
  406.             if (onDisposed == null)
  407.                 onDisposed = new UnityEvent();
  408.             if (onErrorOccurred == null)
  409.                 onErrorOccurred = new ErrorUnityEvent();
  410.  
  411.             initCoroutine = _Initialize();
  412.             StartCoroutine(initCoroutine);
  413.         }
  414.  
  415.         /// <summary>
  416.         /// Initializes this instance.
  417.         /// </summary>
  418.         /// <param name="deviceName">Device name.</param>
  419.         /// <param name="requestedWidth">Requested width.</param>
  420.         /// <param name="requestedHeight">Requested height.</param>
  421.         /// <param name="requestedIsFrontFacing">If set to <c>true</c> requested to using the front camera.</param>
  422.         /// <param name="requestedFPS">Requested FPS.</param>
  423.         /// <param name="rotate90Degree">If set to <c>true</c> requested to rotate camera frame 90 degrees. (clockwise)</param>
  424.         public virtual void Initialize(string deviceName, int requestedWidth, int requestedHeight, bool requestedIsFrontFacing = false, float requestedFPS = 30f, bool rotate90Degree = false)
  425.         {
  426.             if (isInitWaiting)
  427.             {
  428.                 CancelInitCoroutine();
  429.                 ReleaseResources();
  430.             }
  431.  
  432.             this._requestedDeviceName = deviceName;
  433.             this._requestedWidth = requestedWidth;
  434.             this._requestedHeight = requestedHeight;
  435.             this._requestedIsFrontFacing = requestedIsFrontFacing;
  436.             this._requestedFPS = requestedFPS;
  437.             this._rotate90Degree = rotate90Degree;
  438.             if (onInitialized == null)
  439.                 onInitialized = new UnityEvent();
  440.             if (onDisposed == null)
  441.                 onDisposed = new UnityEvent();
  442.             if (onErrorOccurred == null)
  443.                 onErrorOccurred = new ErrorUnityEvent();
  444.  
  445.             initCoroutine = _Initialize();
  446.             StartCoroutine(initCoroutine);
  447.         }
  448.  
  449.         /// <summary>
  450.         /// Initializes this instance by coroutine.
  451.         /// </summary>
  452.         protected virtual IEnumerator _Initialize()
  453.         {
  454.             if (hasInitDone)
  455.             {
  456.                 ReleaseResources();
  457.  
  458.                 if (onDisposed != null)
  459.                     onDisposed.Invoke();
  460.             }
  461.  
  462.             isInitWaiting = true;
  463.  
  464.             float requestedFPS = this.requestedFPS;
  465.  
  466.             // Creates the camera
  467.             if (!String.IsNullOrEmpty(requestedDeviceName))
  468.             {
  469.                 int requestedDeviceIndex = -1;
  470.                 if (Int32.TryParse(requestedDeviceName, out requestedDeviceIndex))
  471.                 {
  472.                     if (requestedDeviceIndex >= 0 && requestedDeviceIndex < WebCamTexture.devices.Length)
  473.                     {
  474.                         webCamDevice = WebCamTexture.devices[requestedDeviceIndex];
  475.  
  476.                         if (avoidAndroidFrontCameraLowLightIssue && webCamDevice.isFrontFacing == true)
  477.                             requestedFPS = 15f;
  478.  
  479.                         if (requestedFPS < 0)
  480.                         {
  481.                             webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight);
  482.                         }
  483.                         else
  484.                         {
  485.                             webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, (int)requestedFPS);
  486.                         }
  487.                     }
  488.                 }
  489.                 else
  490.                 {
  491.                     for (int cameraIndex = 0; cameraIndex < WebCamTexture.devices.Length; cameraIndex++)
  492.                     {
  493.                         if (WebCamTexture.devices[cameraIndex].name == requestedDeviceName)
  494.                         {
  495.                             webCamDevice = WebCamTexture.devices[cameraIndex];
  496.  
  497.                             if (avoidAndroidFrontCameraLowLightIssue && webCamDevice.isFrontFacing == true)
  498.                                 requestedFPS = 15f;
  499.  
  500.                             if (requestedFPS < 0)
  501.                             {
  502.                                 webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight);
  503.                             }
  504.                             else
  505.                             {
  506.                                 webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, (int)requestedFPS);
  507.                             }
  508.                             break;
  509.                         }
  510.                     }
  511.                 }
  512.                 if (webCamTexture == null)
  513.                     Debug.Log("Cannot find camera device " + requestedDeviceName + ".");
  514.             }
  515.  
  516.             if (webCamTexture == null)
  517.             {
  518.                 // Checks how many and which cameras are available on the device
  519.                 for (int cameraIndex = 0; cameraIndex < WebCamTexture.devices.Length; cameraIndex++)
  520.                 {
  521.                     if (WebCamTexture.devices[cameraIndex].isFrontFacing == requestedIsFrontFacing)
  522.                     {
  523.                         webCamDevice = WebCamTexture.devices[cameraIndex];
  524.  
  525.                         if (avoidAndroidFrontCameraLowLightIssue && webCamDevice.isFrontFacing == true)
  526.                             requestedFPS = 15f;
  527.  
  528.                         if (requestedFPS < 0)
  529.                         {
  530.                             webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight);
  531.                         }
  532.                         else
  533.                         {
  534.                             webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, (int)requestedFPS);
  535.                         }
  536.                         break;
  537.                     }
  538.                 }
  539.             }
  540.  
  541.             if (webCamTexture == null)
  542.             {
  543.                 if (WebCamTexture.devices.Length > 0)
  544.                 {
  545.                     webCamDevice = WebCamTexture.devices[0];
  546.  
  547.                     if (avoidAndroidFrontCameraLowLightIssue && webCamDevice.isFrontFacing == true)
  548.                         requestedFPS = 15f;
  549.  
  550.                     if (requestedFPS < 0)
  551.                     {
  552.                         webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight);
  553.                     }
  554.                     else
  555.                     {
  556.                         webCamTexture = new WebCamTexture(webCamDevice.name, requestedWidth, requestedHeight, (int)requestedFPS);
  557.                     }
  558.                 }
  559.                 else
  560.                 {
  561.                     isInitWaiting = false;
  562.  
  563.                     if (onErrorOccurred != null)
  564.                         onErrorOccurred.Invoke(ErrorCode.CAMERA_DEVICE_NOT_EXIST);
  565.  
  566.                     yield break;
  567.                 }
  568.             }
  569.  
  570.             // Starts the camera
  571.             webCamTexture.Play();
  572.  
  573.             int initFrameCount = 0;
  574.             bool isTimeout = false;
  575.  
  576.             while (true)
  577.             {
  578.                 if (initFrameCount > timeoutFrameCount)
  579.                 {
  580.                     isTimeout = true;
  581.                     break;
  582.                 }
  583.                 // 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/)
  584. #if UNITY_IOS && !UNITY_EDITOR && (UNITY_4_6_3 || UNITY_4_6_4 || UNITY_5_0_0 || UNITY_5_0_1)
  585.                 else if (webCamTexture.width > 16 && webCamTexture.height > 16) {
  586. #else
  587.                 else if (webCamTexture.didUpdateThisFrame)
  588.                 {
  589. #if UNITY_IOS && !UNITY_EDITOR && UNITY_5_2
  590.                     while (webCamTexture.width <= 16) {
  591.                         if (initFrameCount > timeoutFrameCount) {
  592.                             isTimeout = true;
  593.                             break;
  594.                         }else {
  595.                             initFrameCount++;
  596.                         }
  597.                         webCamTexture.GetPixels32 ();
  598.                         yield return new WaitForEndOfFrame ();
  599.                     }
  600.                     if (isTimeout) break;
  601. #endif
  602. #endif
  603.  
  604.                     Debug.Log("WebCamTextureToMatHelper:: " + "devicename:" + webCamTexture.deviceName + " name:" + webCamTexture.name + " width:" + webCamTexture.width + " height:" + webCamTexture.height + " fps:" + webCamTexture.requestedFPS
  605.                     + " videoRotationAngle:" + webCamTexture.videoRotationAngle + " videoVerticallyMirrored:" + webCamTexture.videoVerticallyMirrored + " isFrongFacing:" + webCamDevice.isFrontFacing);
  606.  
  607.                     if (colors == null || colors.Length != webCamTexture.width * webCamTexture.height)
  608.                         colors = new Color32[webCamTexture.width * webCamTexture.height];
  609.  
  610.                     frameMat = new Mat(webCamTexture.height, webCamTexture.width, CvType.CV_8UC4);
  611.                     screenOrientation = Screen.orientation;
  612.                     screenWidth = Screen.width;
  613.                     screenHeight = Screen.height;
  614.  
  615.                     bool isRotatedFrame = false;
  616. #if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
  617.                     if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown)
  618.                     {
  619.                         if (!rotate90Degree)
  620.                             isRotatedFrame = true;
  621.                     }
  622.                     else if (rotate90Degree)
  623.                     {
  624.                         isRotatedFrame = true;
  625.                     }
  626. #else
  627.                     if (rotate90Degree)
  628.                         isRotatedFrame = true;
  629. #endif
  630.                     if (isRotatedFrame)
  631.                         rotatedFrameMat = new Mat(webCamTexture.width, webCamTexture.height, CvType.CV_8UC4);
  632.  
  633.                     isInitWaiting = false;
  634.                     hasInitDone = true;
  635.                     initCoroutine = null;
  636.  
  637.                     if (onInitialized != null)
  638.                         onInitialized.Invoke();
  639.  
  640.                     break;
  641.                 }
  642.                 else
  643.                 {
  644.                     initFrameCount++;
  645.                     yield return null;
  646.                 }
  647.             }
  648.  
  649.             if (isTimeout)
  650.             {
  651.                 webCamTexture.Stop();
  652.                 webCamTexture = null;
  653.                 isInitWaiting = false;
  654.                 initCoroutine = null;
  655.  
  656.                 if (onErrorOccurred != null)
  657.                     onErrorOccurred.Invoke(ErrorCode.TIMEOUT);
  658.             }
  659.         }
  660.  
  661.         /// <summary>
  662.         /// Indicates whether this instance has been initialized.
  663.         /// </summary>
  664.         /// <returns><c>true</c>, if this instance has been initialized, <c>false</c> otherwise.</returns>
  665.         public virtual bool IsInitialized()
  666.         {
  667.             return hasInitDone;
  668.         }
  669.  
  670.         /// <summary>
  671.         /// Starts the camera.
  672.         /// </summary>
  673.         public virtual void Play()
  674.         {
  675.             if (hasInitDone)
  676.                 webCamTexture.Play();
  677.         }
  678.  
  679.         /// <summary>
  680.         /// Pauses the active camera.
  681.         /// </summary>
  682.         public virtual void Pause()
  683.         {
  684.             if (hasInitDone)
  685.                 webCamTexture.Pause();
  686.         }
  687.  
  688.         /// <summary>
  689.         /// Stops the active camera.
  690.         /// </summary>
  691.         public virtual void Stop()
  692.         {
  693.             if (hasInitDone)
  694.                 webCamTexture.Stop();
  695.         }
  696.  
  697.         /// <summary>
  698.         /// Indicates whether the active camera is currently playing.
  699.         /// </summary>
  700.         /// <returns><c>true</c>, if the active camera is playing, <c>false</c> otherwise.</returns>
  701.         public virtual bool IsPlaying()
  702.         {
  703.             return hasInitDone ? webCamTexture.isPlaying : false;
  704.         }
  705.  
  706.         /// <summary>
  707.         /// Indicates whether the active camera device is currently front facng.
  708.         /// </summary>
  709.         /// <returns><c>true</c>, if the active camera device is front facng, <c>false</c> otherwise.</returns>
  710.         public virtual bool IsFrontFacing()
  711.         {
  712.             return hasInitDone ? webCamDevice.isFrontFacing : false;
  713.         }
  714.  
  715.         /// <summary>
  716.         /// Returns the active camera device name.
  717.         /// </summary>
  718.         /// <returns>The active camera device name.</returns>
  719.         public virtual string GetDeviceName()
  720.         {
  721.             return hasInitDone ? webCamTexture.deviceName : "";
  722.         }
  723.  
  724.         /// <summary>
  725.         /// Returns the active camera width.
  726.         /// </summary>
  727.         /// <returns>The active camera width.</returns>
  728.         public virtual int GetWidth()
  729.         {
  730.             if (!hasInitDone)
  731.                 return -1;
  732.             return (rotatedFrameMat != null) ? frameMat.height() : frameMat.width();
  733.         }
  734.  
  735.         /// <summary>
  736.         /// Returns the active camera height.
  737.         /// </summary>
  738.         /// <returns>The active camera height.</returns>
  739.         public virtual int GetHeight()
  740.         {
  741.             if (!hasInitDone)
  742.                 return -1;
  743.             return (rotatedFrameMat != null) ? frameMat.width() : frameMat.height();
  744.         }
  745.  
  746.         /// <summary>
  747.         /// Returns the active camera framerate.
  748.         /// </summary>
  749.         /// <returns>The active camera framerate.</returns>
  750.         public virtual float GetFPS()
  751.         {
  752.             return hasInitDone ? webCamTexture.requestedFPS : -1f;
  753.         }
  754.  
  755.         /// <summary>
  756.         /// Returns the active WebcamTexture.
  757.         /// </summary>
  758.         /// <returns>The active WebcamTexture.</returns>
  759.         public virtual WebCamTexture GetWebCamTexture()
  760.         {
  761.             return hasInitDone ? webCamTexture : null;
  762.         }
  763.  
  764.         /// <summary>
  765.         /// Returns the active WebcamDevice.
  766.         /// </summary>
  767.         /// <returns>The active WebcamDevice.</returns>
  768.         public virtual WebCamDevice GetWebCamDevice()
  769.         {
  770.             return webCamDevice;
  771.         }
  772.  
  773.         /// <summary>
  774.         /// Returns the camera to world matrix.
  775.         /// </summary>
  776.         /// <returns>The camera to world matrix.</returns>
  777.         public virtual Matrix4x4 GetCameraToWorldMatrix()
  778.         {
  779.             return Camera.main.cameraToWorldMatrix;
  780.         }
  781.  
  782.         /// <summary>
  783.         /// Returns the projection matrix matrix.
  784.         /// </summary>
  785.         /// <returns>The projection matrix.</returns>
  786.         public virtual Matrix4x4 GetProjectionMatrix()
  787.         {
  788.             return Camera.main.projectionMatrix;
  789.         }
  790.  
  791.         /// <summary>
  792.         /// Indicates whether the video buffer of the frame has been updated.
  793.         /// </summary>
  794.         /// <returns><c>true</c>, if the video buffer has been updated <c>false</c> otherwise.</returns>
  795.         public virtual bool DidUpdateThisFrame()
  796.         {
  797.             if (!hasInitDone)
  798.                 return false;
  799.  
  800. #if UNITY_IOS && !UNITY_EDITOR && (UNITY_4_6_3 || UNITY_4_6_4 || UNITY_5_0_0 || UNITY_5_0_1)
  801.             if (webCamTexture.width > 16 && webCamTexture.height > 16) {
  802.                 return true;
  803.             } else {
  804.                 return false;
  805.             }
  806. #else
  807.             return webCamTexture.didUpdateThisFrame;
  808. #endif
  809.         }
  810.  
  811.         /// <summary>
  812.         /// Gets the mat of the current frame.
  813.         /// The Mat object's type is 'CV_8UC4' (RGBA).
  814.         /// </summary>
  815.         /// <returns>The mat of the current frame.</returns>
  816.         public virtual Mat GetMat()
  817.         {
  818.             if (!hasInitDone || !webCamTexture.isPlaying)
  819.             {
  820.                 return (rotatedFrameMat != null) ? rotatedFrameMat : frameMat;
  821.             }
  822.  
  823.             Utils.webCamTextureToMat(webCamTexture, frameMat, colors, false);
  824.  
  825. #if !UNITY_EDITOR && !(UNITY_STANDALONE || UNITY_WEBGL)
  826.             if (rotatedFrameMat != null)
  827.             {
  828.                 if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown)
  829.                 {
  830.                     // (Orientation is Portrait, rotate90Degree is false)
  831.                     if (webCamDevice.isFrontFacing)
  832.                     {
  833.                         FlipMat(frameMat, !flipHorizontal, !flipVertical);
  834.                     }
  835.                     else
  836.                     {
  837.                         FlipMat(frameMat, flipHorizontal, flipVertical);
  838.                     }
  839.                 }
  840.                 else
  841.                 {
  842.                     // (Orientation is Landscape, rotate90Degrees=true)
  843.                     FlipMat(frameMat, flipVertical, flipHorizontal);
  844.                 }
  845.                 Core.rotate(frameMat, rotatedFrameMat, Core.ROTATE_90_CLOCKWISE);
  846.                 return rotatedFrameMat;
  847.             }
  848.             else
  849.             {
  850.                 if (screenOrientation == ScreenOrientation.Portrait || screenOrientation == ScreenOrientation.PortraitUpsideDown)
  851.                 {
  852.                     // (Orientation is Portrait, rotate90Degree is ture)
  853.                     if (webCamDevice.isFrontFacing)
  854.                     {
  855.                         FlipMat(frameMat, flipHorizontal, flipVertical);
  856.                     }
  857.                     else
  858.                     {
  859.                         FlipMat(frameMat, !flipHorizontal, !flipVertical);
  860.                     }
  861.                 }
  862.                 else
  863.                 {
  864.                     // (Orientation is Landscape, rotate90Degree is false)
  865.                     FlipMat(frameMat, flipVertical, flipHorizontal);
  866.                 }
  867.                 return frameMat;
  868.             }
  869. #else
  870.             FlipMat (frameMat, flipVertical, flipHorizontal);
  871.             if (rotatedFrameMat != null) {                
  872.                 Core.rotate (frameMat, rotatedFrameMat, Core.ROTATE_90_CLOCKWISE);
  873.                 return rotatedFrameMat;
  874.             } else {
  875.                 return frameMat;
  876.             }
  877. #endif
  878.         }
  879.  
  880.         /// <summary>
  881.         /// Flips the mat.
  882.         /// </summary>
  883.         /// <param name="mat">Mat.</param>
  884.         protected virtual void FlipMat(Mat mat, bool flipVertical, bool flipHorizontal)
  885.         {
  886.             //Since the order of pixels of WebCamTexture and Mat is opposite, the initial value of flipCode is set to 0 (flipVertical).
  887.             int flipCode = 0;
  888.  
  889.             if (webCamDevice.isFrontFacing)
  890.             {
  891.                 if (webCamTexture.videoRotationAngle == 0)
  892.                 {
  893.                     flipCode = -1;
  894.                 }
  895.                 else if (webCamTexture.videoRotationAngle == 90)
  896.                 {
  897.                     flipCode = -1;
  898.                 }
  899.                 if (webCamTexture.videoRotationAngle == 180)
  900.                 {
  901.                     flipCode = int.MinValue;
  902.                 }
  903.                 else if (webCamTexture.videoRotationAngle == 270)
  904.                 {
  905.                     flipCode = int.MinValue;
  906.                 }
  907.             }
  908.             else
  909.             {
  910.                 if (webCamTexture.videoRotationAngle == 180)
  911.                 {
  912.                     flipCode = 1;
  913.                 }
  914.                 else if (webCamTexture.videoRotationAngle == 270)
  915.                 {
  916.                     flipCode = 1;
  917.                 }
  918.             }
  919.  
  920.             if (flipVertical)
  921.             {
  922.                 if (flipCode == int.MinValue)
  923.                 {
  924.                     flipCode = 0;
  925.                 }
  926.                 else if (flipCode == 0)
  927.                 {
  928.                     flipCode = int.MinValue;
  929.                 }
  930.                 else if (flipCode == 1)
  931.                 {
  932.                     flipCode = -1;
  933.                 }
  934.                 else if (flipCode == -1)
  935.                 {
  936.                     flipCode = 1;
  937.                 }
  938.             }
  939.  
  940.             if (flipHorizontal)
  941.             {
  942.                 if (flipCode == int.MinValue)
  943.                 {
  944.                     flipCode = 1;
  945.                 }
  946.                 else if (flipCode == 0)
  947.                 {
  948.                     flipCode = -1;
  949.                 }
  950.                 else if (flipCode == 1)
  951.                 {
  952.                     flipCode = int.MinValue;
  953.                 }
  954.                 else if (flipCode == -1)
  955.                 {
  956.                     flipCode = 0;
  957.                 }
  958.             }
  959.  
  960.             if (flipCode > int.MinValue)
  961.             {
  962.                 Core.flip(mat, mat, flipCode);
  963.             }
  964.         }
  965.  
  966.         /// <summary>
  967.         /// Gets the buffer colors.
  968.         /// </summary>
  969.         /// <returns>The buffer colors.</returns>
  970.         public virtual Color32[] GetBufferColors()
  971.         {
  972.             return colors;
  973.         }
  974.  
  975.         /// <summary>
  976.         /// Cancel Init Coroutine.
  977.         /// </summary>
  978.         protected virtual void CancelInitCoroutine()
  979.         {
  980.             if (initCoroutine != null)
  981.             {
  982.                 StopCoroutine(initCoroutine);
  983.                 ((IDisposable)initCoroutine).Dispose();
  984.                 initCoroutine = null;
  985.             }
  986.         }
  987.  
  988.         /// <summary>
  989.         /// To release the resources.
  990.         /// </summary>
  991.         protected virtual void ReleaseResources()
  992.         {
  993.             isInitWaiting = false;
  994.             hasInitDone = false;
  995.  
  996.             if (webCamTexture != null)
  997.             {
  998.                 webCamTexture.Stop();
  999.                 WebCamTexture.Destroy(webCamTexture);
  1000.                 webCamTexture = null;
  1001.             }
  1002.             if (frameMat != null)
  1003.             {
  1004.                 frameMat.Dispose();
  1005.                 frameMat = null;
  1006.             }
  1007.             if (rotatedFrameMat != null)
  1008.             {
  1009.                 rotatedFrameMat.Dispose();
  1010.                 rotatedFrameMat = null;
  1011.             }
  1012.         }
  1013.  
  1014.         /// <summary>
  1015.         /// Releases all resource used by the <see cref="WebCamTextureToMatHelper"/> object.
  1016.         /// </summary>
  1017.         /// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="WebCamTextureToMatHelper"/>. The
  1018.         /// <see cref="Dispose"/> method leaves the <see cref="WebCamTextureToMatHelper"/> in an unusable state. After
  1019.         /// calling <see cref="Dispose"/>, you must release all references to the <see cref="WebCamTextureToMatHelper"/> so
  1020.         /// the garbage collector can reclaim the memory that the <see cref="WebCamTextureToMatHelper"/> was occupying.</remarks>
  1021.         public virtual void Dispose()
  1022.         {
  1023.             if (colors != null)
  1024.                 colors = null;
  1025.  
  1026.             if (isInitWaiting)
  1027.             {
  1028.                 CancelInitCoroutine();
  1029.                 ReleaseResources();
  1030.             }
  1031.             else if (hasInitDone)
  1032.             {
  1033.                 ReleaseResources();
  1034.  
  1035.                 if (onDisposed != null)
  1036.                     onDisposed.Invoke();
  1037.             }
  1038.         }
  1039.     }
  1040. }
  1041.  
  1042. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement