WebCamTextureToMatExample.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. using System;
  2. using System.Collections;
  3. using UnityEngine;
  4. using UnityEngine.SceneManagement;
  5. using OpenCVForUnity.CoreModule;
  6. using OpenCVForUnity.UnityUtils;
  7. using OpenCVForUnity.ImgprocModule;
  8. namespace OpenCVForUnityExample
  9. {
  10. /// <summary>
  11. /// WebCamTextureToMat Example
  12. /// An example of converting a WebCamTexture image to OpenCV's Mat format.
  13. /// </summary>
  14. public class WebCamTextureToMatExample : MonoBehaviour
  15. {
  16. /// <summary>
  17. /// Set the name of the device to use.
  18. /// </summary>
  19. [SerializeField, TooltipAttribute ("Set the name of the device to use.")]
  20. public string requestedDeviceName = null;
  21. /// <summary>
  22. /// Set the width of WebCamTexture.
  23. /// </summary>
  24. [SerializeField, TooltipAttribute ("Set the width of WebCamTexture.")]
  25. public int requestedWidth = 640;
  26. /// <summary>
  27. /// Set the height of WebCamTexture.
  28. /// </summary>
  29. [SerializeField, TooltipAttribute ("Set the height of WebCamTexture.")]
  30. public int requestedHeight = 480;
  31. /// <summary>
  32. /// Set FPS of WebCamTexture.
  33. /// </summary>
  34. [SerializeField, TooltipAttribute ("Set FPS of WebCamTexture.")]
  35. public int requestedFPS = 30;
  36. /// <summary>
  37. /// Set whether to use the front facing camera.
  38. /// </summary>
  39. [SerializeField, TooltipAttribute ("Set whether to use the front facing camera.")]
  40. public bool requestedIsFrontFacing = false;
  41. /// <summary>
  42. /// The webcam texture.
  43. /// </summary>
  44. WebCamTexture webCamTexture;
  45. /// <summary>
  46. /// The webcam device.
  47. /// </summary>
  48. WebCamDevice webCamDevice;
  49. /// <summary>
  50. /// The rgba mat.
  51. /// </summary>
  52. Mat rgbaMat;
  53. /// <summary>
  54. /// The colors.
  55. /// </summary>
  56. Color32[] colors;
  57. /// <summary>
  58. /// The texture.
  59. /// </summary>
  60. Texture2D texture;
  61. /// <summary>
  62. /// Indicates whether this instance is waiting for initialization to complete.
  63. /// </summary>
  64. bool isInitWaiting = false;
  65. /// <summary>
  66. /// Indicates whether this instance has been initialized.
  67. /// </summary>
  68. bool hasInitDone = false;
  69. /// <summary>
  70. /// The FPS monitor.
  71. /// </summary>
  72. FpsMonitor fpsMonitor;
  73. // Use this for initialization
  74. void Start ()
  75. {
  76. fpsMonitor = GetComponent<FpsMonitor> ();
  77. Initialize ();
  78. }
  79. /// <summary>
  80. /// Initializes webcam texture.
  81. /// </summary>
  82. private void Initialize ()
  83. {
  84. if (isInitWaiting)
  85. return;
  86. #if UNITY_ANDROID && !UNITY_EDITOR
  87. // Set the requestedFPS parameter to avoid the problem of the WebCamTexture image becoming low light on some Android devices (e.g. Google Pixel, Pixel2).
  88. // https://forum.unity.com/threads/android-webcamtexture-in-low-light-only-some-models.520656/
  89. // https://forum.unity.com/threads/released-opencv-for-unity.277080/page-33#post-3445178
  90. if (requestedIsFrontFacing) {
  91. int rearCameraFPS = requestedFPS;
  92. requestedFPS = 15;
  93. StartCoroutine (_Initialize ());
  94. requestedFPS = rearCameraFPS;
  95. } else {
  96. StartCoroutine (_Initialize ());
  97. }
  98. #else
  99. StartCoroutine (_Initialize ());
  100. #endif
  101. }
  102. /// <summary>
  103. /// Initializes webcam texture by coroutine.
  104. /// </summary>
  105. private IEnumerator _Initialize ()
  106. {
  107. if (hasInitDone)
  108. Dispose ();
  109. isInitWaiting = true;
  110. // Creates the camera
  111. if (!String.IsNullOrEmpty (requestedDeviceName)) {
  112. int requestedDeviceIndex = -1;
  113. if (Int32.TryParse (requestedDeviceName, out requestedDeviceIndex)) {
  114. if (requestedDeviceIndex >= 0 && requestedDeviceIndex < WebCamTexture.devices.Length) {
  115. webCamDevice = WebCamTexture.devices [requestedDeviceIndex];
  116. webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
  117. }
  118. } else {
  119. for (int cameraIndex = 0; cameraIndex < WebCamTexture.devices.Length; cameraIndex++) {
  120. if (WebCamTexture.devices [cameraIndex].name == requestedDeviceName) {
  121. webCamDevice = WebCamTexture.devices [cameraIndex];
  122. webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
  123. break;
  124. }
  125. }
  126. }
  127. if (webCamTexture == null)
  128. Debug.Log ("Cannot find camera device " + requestedDeviceName + ".");
  129. }
  130. if (webCamTexture == null) {
  131. // Checks how many and which cameras are available on the device
  132. for (int cameraIndex = 0; cameraIndex < WebCamTexture.devices.Length; cameraIndex++) {
  133. if (WebCamTexture.devices [cameraIndex].isFrontFacing == requestedIsFrontFacing) {
  134. webCamDevice = WebCamTexture.devices [cameraIndex];
  135. webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
  136. break;
  137. }
  138. }
  139. }
  140. if (webCamTexture == null) {
  141. if (WebCamTexture.devices.Length > 0) {
  142. webCamDevice = WebCamTexture.devices [0];
  143. webCamTexture = new WebCamTexture (webCamDevice.name, requestedWidth, requestedHeight, requestedFPS);
  144. } else {
  145. Debug.LogError ("Camera device does not exist.");
  146. isInitWaiting = false;
  147. yield break;
  148. }
  149. }
  150. // Starts the camera.
  151. webCamTexture.Play ();
  152. while (true) {
  153. // 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/).
  154. #if UNITY_IOS && !UNITY_EDITOR && (UNITY_4_6_3 || UNITY_4_6_4 || UNITY_5_0_0 || UNITY_5_0_1)
  155. if (webCamTexture.width > 16 && webCamTexture.height > 16) {
  156. #else
  157. if (webCamTexture.didUpdateThisFrame) {
  158. #if UNITY_IOS && !UNITY_EDITOR && UNITY_5_2
  159. while (webCamTexture.width <= 16) {
  160. webCamTexture.GetPixels32 ();
  161. yield return new WaitForEndOfFrame ();
  162. }
  163. #endif
  164. #endif
  165. Debug.Log ("name:" + webCamTexture.deviceName + " width:" + webCamTexture.width + " height:" + webCamTexture.height + " fps:" + webCamTexture.requestedFPS);
  166. Debug.Log ("videoRotationAngle:" + webCamTexture.videoRotationAngle + " videoVerticallyMirrored:" + webCamTexture.videoVerticallyMirrored + " isFrongFacing:" + webCamDevice.isFrontFacing);
  167. isInitWaiting = false;
  168. hasInitDone = true;
  169. OnInited ();
  170. break;
  171. } else {
  172. yield return null;
  173. }
  174. }
  175. }
  176. /// <summary>
  177. /// Releases all resource.
  178. /// </summary>
  179. private void Dispose ()
  180. {
  181. isInitWaiting = false;
  182. hasInitDone = false;
  183. if (webCamTexture != null) {
  184. webCamTexture.Stop ();
  185. WebCamTexture.Destroy (webCamTexture);
  186. webCamTexture = null;
  187. }
  188. if (rgbaMat != null) {
  189. rgbaMat.Dispose ();
  190. rgbaMat = null;
  191. }
  192. if (texture != null) {
  193. Texture2D.Destroy (texture);
  194. texture = null;
  195. }
  196. }
  197. /// <summary>
  198. /// Raises the webcam texture initialized event.
  199. /// </summary>
  200. private void OnInited ()
  201. {
  202. if (colors == null || colors.Length != webCamTexture.width * webCamTexture.height)
  203. colors = new Color32[webCamTexture.width * webCamTexture.height];
  204. if (texture == null || texture.width != webCamTexture.width || texture.height != webCamTexture.height)
  205. texture = new Texture2D (webCamTexture.width, webCamTexture.height, TextureFormat.RGBA32, false);
  206. rgbaMat = new Mat (webCamTexture.height, webCamTexture.width, CvType.CV_8UC4);
  207. gameObject.GetComponent<Renderer> ().material.mainTexture = texture;
  208. gameObject.transform.localScale = new Vector3 (webCamTexture.width, webCamTexture.height, 1);
  209. Debug.Log ("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
  210. if (fpsMonitor != null) {
  211. fpsMonitor.Add ("width", rgbaMat.width ().ToString ());
  212. fpsMonitor.Add ("height", rgbaMat.height ().ToString ());
  213. fpsMonitor.Add ("orientation", Screen.orientation.ToString ());
  214. }
  215. float width = rgbaMat.width ();
  216. float height = rgbaMat.height ();
  217. float widthScale = (float)Screen.width / width;
  218. float heightScale = (float)Screen.height / height;
  219. if (widthScale < heightScale) {
  220. Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
  221. } else {
  222. Camera.main.orthographicSize = height / 2;
  223. }
  224. }
  225. // Update is called once per frame
  226. void Update ()
  227. {
  228. if (hasInitDone && webCamTexture.isPlaying && webCamTexture.didUpdateThisFrame) {
  229. Utils.webCamTextureToMat (webCamTexture, rgbaMat, colors);
  230. // 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);
  231. Utils.matToTexture2D (rgbaMat, texture, colors);
  232. }
  233. }
  234. /// <summary>
  235. /// Raises the destroy event.
  236. /// </summary>
  237. void OnDestroy ()
  238. {
  239. Dispose ();
  240. }
  241. /// <summary>
  242. /// Raises the back button click event.
  243. /// </summary>
  244. public void OnBackButtonClick ()
  245. {
  246. SceneManager.LoadScene ("OpenCVForUnityExample");
  247. }
  248. /// <summary>
  249. /// Raises the play button click event.
  250. /// </summary>
  251. public void OnPlayButtonClick ()
  252. {
  253. if (hasInitDone)
  254. webCamTexture.Play ();
  255. }
  256. /// <summary>
  257. /// Raises the pause button click event.
  258. /// </summary>
  259. public void OnPauseButtonClick ()
  260. {
  261. if (hasInitDone)
  262. webCamTexture.Pause ();
  263. }
  264. /// <summary>
  265. /// Raises the stop button click event.
  266. /// </summary>
  267. public void OnStopButtonClick ()
  268. {
  269. if (hasInitDone)
  270. webCamTexture.Stop ();
  271. }
  272. /// <summary>
  273. /// Raises the change camera button click event.
  274. /// </summary>
  275. public void OnChangeCameraButtonClick ()
  276. {
  277. if (hasInitDone) {
  278. requestedDeviceName = null;
  279. requestedIsFrontFacing = !requestedIsFrontFacing;
  280. Initialize ();
  281. }
  282. }
  283. }
  284. }