TensorFlowWebCamTextureExample.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #if !UNITY_WSA_10_0
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. using UnityEngine.UI;
  7. using UnityEngine.SceneManagement;
  8. using OpenCVForUnity.CoreModule;
  9. using OpenCVForUnity.DnnModule;
  10. using OpenCVForUnity.ImgprocModule;
  11. using OpenCVForUnity.UnityUtils;
  12. using OpenCVForUnity.UnityUtils.Helper;
  13. namespace OpenCVForUnityExample
  14. {
  15. /// <summary>
  16. /// TensorFlow WebCamTexture Example
  17. /// An example of using OpenCV dnn module with Tensorflow Inception model.
  18. /// Referring to https://github.com/opencv/opencv/blob/master/samples/dnn/tf_inception.cpp.
  19. /// </summary>
  20. [RequireComponent (typeof(WebCamTextureToMatHelper))]
  21. public class TensorFlowWebCamTextureExample : MonoBehaviour
  22. {
  23. /// <summary>
  24. /// The texture.
  25. /// </summary>
  26. Texture2D texture;
  27. /// <summary>
  28. /// The webcam texture to mat helper.
  29. /// </summary>
  30. WebCamTextureToMatHelper webCamTextureToMatHelper;
  31. /// <summary>
  32. /// The bgr mat.
  33. /// </summary>
  34. Mat bgrMat;
  35. /// <summary>
  36. /// The BLOB.
  37. /// </summary>
  38. Mat blob;
  39. /// <summary>
  40. /// The net.
  41. /// </summary>
  42. Net net;
  43. /// <summary>
  44. /// The classes.
  45. /// </summary>
  46. List<string> classes;
  47. /// <summary>
  48. /// The FPS monitor.
  49. /// </summary>
  50. FpsMonitor fpsMonitor;
  51. string tensorflow_inception_graph_pb_filepath;
  52. string imagenet_comp_graph_label_strings_txt_filepath;
  53. #if UNITY_WEBGL && !UNITY_EDITOR
  54. IEnumerator getFilePath_Coroutine;
  55. #endif
  56. // Use this for initialization
  57. void Start ()
  58. {
  59. fpsMonitor = GetComponent<FpsMonitor> ();
  60. webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper> ();
  61. #if UNITY_WEBGL && !UNITY_EDITOR
  62. getFilePath_Coroutine = GetFilePath ();
  63. StartCoroutine (getFilePath_Coroutine);
  64. #else
  65. tensorflow_inception_graph_pb_filepath = Utils.getFilePath ("dnn/tensorflow_inception_graph.pb");
  66. imagenet_comp_graph_label_strings_txt_filepath = Utils.getFilePath ("dnn/imagenet_comp_graph_label_strings.txt");
  67. Run ();
  68. #endif
  69. }
  70. #if UNITY_WEBGL && !UNITY_EDITOR
  71. private IEnumerator GetFilePath()
  72. {
  73. var getFilePathAsync_0_Coroutine = Utils.getFilePathAsync ("dnn/tensorflow_inception_graph.pb", (result) => {
  74. tensorflow_inception_graph_pb_filepath = result;
  75. });
  76. yield return getFilePathAsync_0_Coroutine;
  77. var getFilePathAsync_1_Coroutine = Utils.getFilePathAsync ("dnn/imagenet_comp_graph_label_strings.txt", (result) => {
  78. imagenet_comp_graph_label_strings_txt_filepath = result;
  79. });
  80. yield return getFilePathAsync_1_Coroutine;
  81. getFilePath_Coroutine = null;
  82. Run ();
  83. }
  84. #endif
  85. // Use this for initialization
  86. void Run ()
  87. {
  88. //if true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.
  89. Utils.setDebugMode (true);
  90. net = Dnn.readNetFromTensorflow (tensorflow_inception_graph_pb_filepath);
  91. #if !UNITY_WSA_10_0
  92. if (net.empty ()) {
  93. Debug.LogError ("model file is not loaded. The model and class names list can be downloaded here: \"https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip\". Please copy to “Assets/StreamingAssets/dnn/” folder. ");
  94. }
  95. #endif
  96. classes = readClassNames (imagenet_comp_graph_label_strings_txt_filepath);
  97. #if !UNITY_WSA_10_0
  98. if (classes == null) {
  99. Debug.LogError ("class names list file is not loaded. The model and class names list can be downloaded here: \"https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip\". Please copy to “Assets/StreamingAssets/dnn/” folder. ");
  100. }
  101. #endif
  102. #if UNITY_ANDROID && !UNITY_EDITOR
  103. // Avoids the front camera low light issue that occurs in only some Android devices (e.g. Google Pixel, Pixel2).
  104. webCamTextureToMatHelper.avoidAndroidFrontCameraLowLightIssue = true;
  105. #endif
  106. webCamTextureToMatHelper.Initialize ();
  107. }
  108. /// <summary>
  109. /// Raises the webcam texture to mat helper initialized event.
  110. /// </summary>
  111. public void OnWebCamTextureToMatHelperInitialized ()
  112. {
  113. Debug.Log ("OnWebCamTextureToMatHelperInitialized");
  114. Mat webCamTextureMat = webCamTextureToMatHelper.GetMat ();
  115. texture = new Texture2D (webCamTextureMat.cols (), webCamTextureMat.rows (), TextureFormat.RGBA32, false);
  116. gameObject.GetComponent<Renderer> ().material.mainTexture = texture;
  117. gameObject.transform.localScale = new Vector3 (webCamTextureMat.cols (), webCamTextureMat.rows (), 1);
  118. Debug.Log ("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
  119. if (fpsMonitor != null) {
  120. fpsMonitor.Add ("width", webCamTextureMat.width ().ToString ());
  121. fpsMonitor.Add ("height", webCamTextureMat.height ().ToString ());
  122. fpsMonitor.Add ("orientation", Screen.orientation.ToString ());
  123. }
  124. float width = webCamTextureMat.width ();
  125. float height = webCamTextureMat.height ();
  126. float widthScale = (float)Screen.width / width;
  127. float heightScale = (float)Screen.height / height;
  128. if (widthScale < heightScale) {
  129. Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
  130. } else {
  131. Camera.main.orthographicSize = height / 2;
  132. }
  133. bgrMat = new Mat (webCamTextureMat.rows (), webCamTextureMat.cols (), CvType.CV_8UC3);
  134. }
  135. /// <summary>
  136. /// Raises the webcam texture to mat helper disposed event.
  137. /// </summary>
  138. public void OnWebCamTextureToMatHelperDisposed ()
  139. {
  140. Debug.Log ("OnWebCamTextureToMatHelperDisposed");
  141. if (bgrMat != null)
  142. bgrMat.Dispose ();
  143. if (texture != null) {
  144. Texture2D.Destroy (texture);
  145. texture = null;
  146. }
  147. }
  148. /// <summary>
  149. /// Raises the webcam texture to mat helper error occurred event.
  150. /// </summary>
  151. /// <param name="errorCode">Error code.</param>
  152. public void OnWebCamTextureToMatHelperErrorOccurred (WebCamTextureToMatHelper.ErrorCode errorCode)
  153. {
  154. Debug.Log ("OnWebCamTextureToMatHelperErrorOccurred " + errorCode);
  155. }
  156. // Update is called once per frame
  157. void Update ()
  158. {
  159. if (webCamTextureToMatHelper.IsPlaying () && webCamTextureToMatHelper.DidUpdateThisFrame ()) {
  160. Mat rgbaMat = webCamTextureToMatHelper.GetMat ();
  161. if (net.empty () || classes == null) {
  162. Imgproc.putText (rgbaMat, "model file is not loaded.", new Point (5, rgbaMat.rows () - 30), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar (255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
  163. Imgproc.putText (rgbaMat, "Please read console message.", new Point (5, rgbaMat.rows () - 10), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar (255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
  164. } else {
  165. Imgproc.cvtColor (rgbaMat, bgrMat, Imgproc.COLOR_RGBA2BGR);
  166. blob = Dnn.blobFromImage (bgrMat, 1, new Size (224, 224), new Scalar (104, 117, 123), false, true);
  167. net.setInput (blob);
  168. Mat prob = net.forward ();
  169. Core.MinMaxLocResult minmax = Core.minMaxLoc (prob.reshape (1, 1));
  170. // Debug.Log ("Best match " + (int)minmax.maxLoc.x);
  171. // Debug.Log ("Best match class " + classes [(int)minmax.maxLoc.x]);
  172. // Debug.Log ("Probability: " + minmax.maxVal * 100 + "%");
  173. prob.Dispose ();
  174. //Imgproc.putText (rgbaMat, "Best match class " + classes [(int)minmax.maxLoc.x], new Point (5, rgbaMat.rows () - 10), Core.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar (255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
  175. if (fpsMonitor != null) {
  176. fpsMonitor.consoleText = "Best match class " + classes [(int)minmax.maxLoc.x];
  177. }
  178. }
  179. Utils.fastMatToTexture2D (rgbaMat, texture);
  180. }
  181. }
  182. /// <summary>
  183. /// Raises the disable event.
  184. /// </summary>
  185. void OnDisable ()
  186. {
  187. webCamTextureToMatHelper.Dispose ();
  188. if (blob != null)
  189. blob.Dispose ();
  190. if (net != null)
  191. net.Dispose ();
  192. Utils.setDebugMode (false);
  193. #if UNITY_WEBGL && !UNITY_EDITOR
  194. if (getFilePath_Coroutine != null) {
  195. StopCoroutine (getFilePath_Coroutine);
  196. ((IDisposable)getFilePath_Coroutine).Dispose ();
  197. }
  198. #endif
  199. }
  200. /// <summary>
  201. /// Raises the back button click event.
  202. /// </summary>
  203. public void OnBackButtonClick ()
  204. {
  205. SceneManager.LoadScene ("OpenCVForUnityExample");
  206. }
  207. /// <summary>
  208. /// Raises the play button click event.
  209. /// </summary>
  210. public void OnPlayButtonClick ()
  211. {
  212. webCamTextureToMatHelper.Play ();
  213. }
  214. /// <summary>
  215. /// Raises the pause button click event.
  216. /// </summary>
  217. public void OnPauseButtonClick ()
  218. {
  219. webCamTextureToMatHelper.Pause ();
  220. }
  221. /// <summary>
  222. /// Raises the stop button click event.
  223. /// </summary>
  224. public void OnStopButtonClick ()
  225. {
  226. webCamTextureToMatHelper.Stop ();
  227. }
  228. /// <summary>
  229. /// Raises the change camera button click event.
  230. /// </summary>
  231. public void OnChangeCameraButtonClick ()
  232. {
  233. webCamTextureToMatHelper.requestedIsFrontFacing = !webCamTextureToMatHelper.IsFrontFacing ();
  234. }
  235. private List<string> readClassNames (string filename)
  236. {
  237. List<string> classNames = new List<string> ();
  238. System.IO.StreamReader cReader = null;
  239. try {
  240. cReader = new System.IO.StreamReader (filename, System.Text.Encoding.Default);
  241. while (cReader.Peek () >= 0) {
  242. string name = cReader.ReadLine ();
  243. classNames.Add (name);
  244. }
  245. } catch (System.Exception ex) {
  246. Debug.LogError (ex.Message);
  247. return null;
  248. } finally {
  249. if (cReader != null)
  250. cReader.Close ();
  251. }
  252. return classNames;
  253. }
  254. }
  255. }
  256. #endif