GreenScreenExample.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. using System.Collections;
  2. using UnityEngine;
  3. using UnityEngine.SceneManagement;
  4. using UnityEngine.UI;
  5. using UnityEngine.EventSystems;
  6. using OpenCVForUnity.CoreModule;
  7. using OpenCVForUnity.ImgprocModule;
  8. using OpenCVForUnity.UnityUtils;
  9. using OpenCVForUnity.UnityUtils.Helper;
  10. namespace OpenCVForUnityExample
  11. {
  12. /// <summary>
  13. /// Green Screen Example
  14. /// Referring to https://gist.github.com/drscotthawley/2d6bbffce9dda5f3057b4879c3bd4422.
  15. /// </summary>
  16. [RequireComponent (typeof(WebCamTextureToMatHelper))]
  17. public class GreenScreenExample : MonoBehaviour
  18. {
  19. /// <summary>
  20. /// The thresh.
  21. /// </summary>
  22. [Range (0, 255)]
  23. public float thresh = 50.0f;
  24. /// <summary>
  25. /// The background raw image.
  26. /// </summary>
  27. public RawImage bgRawImage;
  28. /// <summary>
  29. /// The texture.
  30. /// </summary>
  31. Texture2D texture;
  32. /// <summary>
  33. /// The webcam texture to mat helper.
  34. /// </summary>
  35. WebCamTextureToMatHelper webCamTextureToMatHelper;
  36. /// <summary>
  37. /// The background mat.
  38. /// </summary>
  39. Mat bgMat;
  40. /// <summary>
  41. /// The foreground mask mat.
  42. /// </summary>
  43. Mat fgMaskMat;
  44. /// <summary>
  45. /// The background mask mat.
  46. /// </summary>
  47. Mat bgMaskMat;
  48. /// <summary>
  49. /// The green mat.
  50. /// </summary>
  51. Mat greenMat;
  52. /// <summary>
  53. /// The background texture.
  54. /// </summary>
  55. Texture2D bgTexture;
  56. /// <summary>
  57. /// The FPS monitor.
  58. /// </summary>
  59. FpsMonitor fpsMonitor;
  60. // Use this for initialization
  61. void Start ()
  62. {
  63. fpsMonitor = GetComponent<FpsMonitor> ();
  64. webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper> ();
  65. #if UNITY_ANDROID && !UNITY_EDITOR
  66. // Avoids the front camera low light issue that occurs in only some Android devices (e.g. Google Pixel, Pixel2).
  67. webCamTextureToMatHelper.avoidAndroidFrontCameraLowLightIssue = true;
  68. #endif
  69. webCamTextureToMatHelper.Initialize ();
  70. }
  71. /// <summary>
  72. /// Raises the webcam texture to mat helper initialized event.
  73. /// </summary>
  74. public void OnWebCamTextureToMatHelperInitialized ()
  75. {
  76. Debug.Log ("OnWebCamTextureToMatHelperInitialized");
  77. Mat webCamTextureMat = webCamTextureToMatHelper.GetMat ();
  78. texture = new Texture2D (webCamTextureMat.cols (), webCamTextureMat.rows (), TextureFormat.RGBA32, false);
  79. gameObject.GetComponent<Renderer> ().material.mainTexture = texture;
  80. gameObject.transform.localScale = new Vector3 (webCamTextureMat.cols (), webCamTextureMat.rows (), 1);
  81. Debug.Log ("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
  82. if (fpsMonitor != null) {
  83. fpsMonitor.Add ("width", webCamTextureMat.width ().ToString ());
  84. fpsMonitor.Add ("height", webCamTextureMat.height ().ToString ());
  85. fpsMonitor.Add ("orientation", Screen.orientation.ToString ());
  86. fpsMonitor.consoleText = "SPACE KEY or TOUCH SCREEN: Reset backgroud image.";
  87. }
  88. float width = webCamTextureMat.width ();
  89. float height = webCamTextureMat.height ();
  90. float widthScale = (float)Screen.width / width;
  91. float heightScale = (float)Screen.height / height;
  92. if (widthScale < heightScale) {
  93. Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
  94. } else {
  95. Camera.main.orthographicSize = height / 2;
  96. }
  97. bgMat = new Mat (webCamTextureMat.rows (), webCamTextureMat.cols (), CvType.CV_8UC4);
  98. fgMaskMat = new Mat (webCamTextureMat.rows (), webCamTextureMat.cols (), CvType.CV_8UC1);
  99. bgMaskMat = new Mat (webCamTextureMat.rows (), webCamTextureMat.cols (), CvType.CV_8UC1);
  100. greenMat = new Mat (webCamTextureMat.rows (), webCamTextureMat.cols (), CvType.CV_8UC4, new Scalar (0, 255, 0, 255));
  101. bgTexture = new Texture2D (bgMat.cols (), bgMat.rows (), TextureFormat.RGBA32, false);
  102. }
  103. /// <summary>
  104. /// Raises the webcam texture to mat helper disposed event.
  105. /// </summary>
  106. public void OnWebCamTextureToMatHelperDisposed ()
  107. {
  108. Debug.Log ("OnWebCamTextureToMatHelperDisposed");
  109. if (bgMat != null) {
  110. bgMat.Dispose ();
  111. bgMat = null;
  112. }
  113. if (fgMaskMat != null) {
  114. fgMaskMat.Dispose ();
  115. fgMaskMat = null;
  116. }
  117. if (bgMaskMat != null) {
  118. bgMaskMat.Dispose ();
  119. bgMaskMat = null;
  120. }
  121. if (greenMat != null) {
  122. greenMat.Dispose ();
  123. greenMat = null;
  124. }
  125. if (texture != null) {
  126. Texture2D.Destroy (texture);
  127. texture = null;
  128. }
  129. }
  130. /// <summary>
  131. /// Raises the webcam texture to mat helper error occurred event.
  132. /// </summary>
  133. /// <param name="errorCode">Error code.</param>
  134. public void OnWebCamTextureToMatHelperErrorOccurred (WebCamTextureToMatHelper.ErrorCode errorCode)
  135. {
  136. Debug.Log ("OnWebCamTextureToMatHelperErrorOccurred " + errorCode);
  137. }
  138. // Update is called once per frame
  139. void Update ()
  140. {
  141. bool isTouched = false;
  142. #if ((UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR)
  143. if (Input.touchCount == 1) {
  144. Touch t = Input.GetTouch(0);
  145. if (t.phase == TouchPhase.Ended && !EventSystem.current.IsPointerOverGameObject (t.fingerId)) {
  146. isTouched = true;
  147. }
  148. }
  149. #else
  150. if (Input.GetKeyUp (KeyCode.Space)) {
  151. isTouched = true;
  152. }
  153. #endif
  154. if (webCamTextureToMatHelper.IsPlaying () && webCamTextureToMatHelper.DidUpdateThisFrame ()) {
  155. Mat rgbaMat = webCamTextureToMatHelper.GetMat ();
  156. if (isTouched) {
  157. rgbaMat.copyTo (bgMat);
  158. setBgTexture (bgMat);
  159. }
  160. //set fgMaskMat
  161. findFgMaskMat (rgbaMat, bgMat, thresh);
  162. //set bgMaskMat
  163. Core.bitwise_not (fgMaskMat, bgMaskMat);
  164. //copy greenMat using bgMaskMat
  165. greenMat.copyTo (rgbaMat, bgMaskMat);
  166. //Imgproc.putText (rgbaMat, "SPACE KEY or TOUCH SCREEN: Reset backgroud image.", new Point (5, rgbaMat.rows () - 10), Core.FONT_HERSHEY_SIMPLEX, 0.6, new Scalar (255, 255, 255, 255), 2, Imgproc.LINE_AA, false);
  167. Utils.fastMatToTexture2D (rgbaMat, texture);
  168. }
  169. }
  170. /// <summary>
  171. /// Finds the foreground mask mat.
  172. /// </summary>
  173. /// <param name="fgMat">Fg mat.</param>
  174. /// <param name="bgMat">Background mat.</param>
  175. /// <param name="thresh">Thresh.</param>
  176. private void findFgMaskMat (Mat fgMat, Mat bgMat, float thresh = 13.0f)
  177. {
  178. Mat diff1 = new Mat ();
  179. Core.absdiff (fgMat, bgMat, diff1);
  180. Mat diff2 = new Mat ();
  181. Core.absdiff (bgMat, fgMat, diff2);
  182. Mat diff = diff1 + diff2;
  183. Imgproc.threshold (diff, diff, thresh, 0, Imgproc.THRESH_TOZERO);
  184. Imgproc.cvtColor (diff, fgMaskMat, Imgproc.COLOR_RGBA2GRAY);
  185. Imgproc.threshold (fgMaskMat, fgMaskMat, 10, 0, Imgproc.THRESH_TOZERO);
  186. Imgproc.threshold (fgMaskMat, fgMaskMat, 0, 255, Imgproc.THRESH_BINARY);
  187. diff1.Dispose ();
  188. diff2.Dispose ();
  189. diff.Dispose ();
  190. }
  191. /// <summary>
  192. /// Sets the background texture.
  193. /// </summary>
  194. /// <param name="bgMat">Background mat.</param>
  195. private void setBgTexture (Mat bgMat)
  196. {
  197. Utils.matToTexture2D (bgMat, bgTexture);
  198. bgRawImage.texture = bgTexture;
  199. bgRawImage.rectTransform.localScale = new Vector3 (1.0f, (float)bgMat.height () / (float)bgMat.width (), 1.0f);
  200. }
  201. /// <summary>
  202. /// Raises the destroy event.
  203. /// </summary>
  204. void OnDestroy ()
  205. {
  206. webCamTextureToMatHelper.Dispose ();
  207. }
  208. /// <summary>
  209. /// Raises the back button click event.
  210. /// </summary>
  211. public void OnBackButtonClick ()
  212. {
  213. SceneManager.LoadScene ("OpenCVForUnityExample");
  214. }
  215. /// <summary>
  216. /// Raises the play button click event.
  217. /// </summary>
  218. public void OnPlayButtonClick ()
  219. {
  220. webCamTextureToMatHelper.Play ();
  221. }
  222. /// <summary>
  223. /// Raises the pause button click event.
  224. /// </summary>
  225. public void OnPauseButtonClick ()
  226. {
  227. webCamTextureToMatHelper.Pause ();
  228. }
  229. /// <summary>
  230. /// Raises the stop button click event.
  231. /// </summary>
  232. public void OnStopButtonClick ()
  233. {
  234. webCamTextureToMatHelper.Stop ();
  235. }
  236. /// <summary>
  237. /// Raises the change camera button click event.
  238. /// </summary>
  239. public void OnChangeCameraButtonClick ()
  240. {
  241. webCamTextureToMatHelper.requestedIsFrontFacing = !webCamTextureToMatHelper.IsFrontFacing ();
  242. }
  243. }
  244. }