BackgroundSubtractorExample.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. using OpenCVForUnity.BgsegmModule;
  2. using OpenCVForUnity.CoreModule;
  3. using OpenCVForUnity.ImgprocModule;
  4. using OpenCVForUnity.UnityUtils;
  5. using OpenCVForUnity.UnityUtils.Helper;
  6. using OpenCVForUnity.VideoModule;
  7. using System;
  8. using UnityEngine;
  9. using UnityEngine.SceneManagement;
  10. using UnityEngine.UI;
  11. namespace OpenCVForUnityExample
  12. {
  13. /// <summary>
  14. /// Background Subtractor Example
  15. /// This example is intended for comparison of different background subtraction algorithms presented in OpenCV.
  16. /// </summary>
  17. [RequireComponent(typeof(VideoCaptureToMatHelper))]
  18. public class BackgroundSubtractorExample : MonoBehaviour
  19. {
  20. /// <summary>
  21. /// The background subtractor algorithm dropdown.
  22. /// </summary>
  23. public Dropdown backgroundSubtractorAlgorithmDropdown;
  24. /// <summary>
  25. /// The background subtractor algorithm.
  26. /// </summary>
  27. public BackgroundSubtractorAlgorithmPreset backgroundSubtractorAlgorithm = BackgroundSubtractorAlgorithmPreset.KNN;
  28. /// <summary>
  29. /// The enable MorphologyEx toggle.
  30. /// </summary>
  31. public Toggle enableMorphologyExToggle;
  32. /// <summary>
  33. /// The show background image toggle.
  34. /// </summary>
  35. public Toggle showBackgroundImageToggle;
  36. /// <summary>
  37. /// The texture.
  38. /// </summary>
  39. Texture2D texture;
  40. /// <summary>
  41. /// The video capture to mat helper.
  42. /// </summary>
  43. VideoCaptureToMatHelper sourceToMatHelper;
  44. /// <summary>
  45. /// The background substractor.
  46. /// </summary>
  47. BackgroundSubtractor backgroundSubstractor;
  48. /// <summary>
  49. /// The fgmask mat.
  50. /// </summary>
  51. Mat fgmaskMat;
  52. /// <summary>
  53. /// The kernel for morphologyEx method.
  54. /// </summary>
  55. Mat kernel;
  56. /// <summary>
  57. /// The stopwatch.
  58. /// </summary>
  59. System.Diagnostics.Stopwatch watch;
  60. /// <summary>
  61. /// The FPS monitor.
  62. /// </summary>
  63. FpsMonitor fpsMonitor;
  64. /// <summary>
  65. /// VIDEO_FILENAME
  66. /// </summary>
  67. protected static readonly string VIDEO_FILENAME = "OpenCVForUnity/768x576_mjpeg.mjpeg";
  68. // Use this for initialization
  69. void Start()
  70. {
  71. fpsMonitor = GetComponent<FpsMonitor>();
  72. sourceToMatHelper = gameObject.GetComponent<VideoCaptureToMatHelper>();
  73. if (string.IsNullOrEmpty(sourceToMatHelper.requestedVideoFilePath))
  74. sourceToMatHelper.requestedVideoFilePath = VIDEO_FILENAME;
  75. sourceToMatHelper.outputColorFormat = VideoCaptureToMatHelper.ColorFormat.RGB; // Background Subtractor API must handle 3 channels Mat image.
  76. sourceToMatHelper.Initialize();
  77. // Update GUI state
  78. backgroundSubtractorAlgorithmDropdown.value = Array.IndexOf(System.Enum.GetNames(typeof(BackgroundSubtractorAlgorithmPreset)), backgroundSubtractorAlgorithm.ToString());
  79. enableMorphologyExToggle.isOn = false;
  80. showBackgroundImageToggle.isOn = false;
  81. CreateBackgroundSubstractor(backgroundSubtractorAlgorithm);
  82. kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(3, 3));
  83. watch = new System.Diagnostics.Stopwatch();
  84. if (fpsMonitor != null)
  85. {
  86. fpsMonitor.Add("time: ", "");
  87. }
  88. }
  89. protected void CreateBackgroundSubstractor(BackgroundSubtractorAlgorithmPreset algorithm)
  90. {
  91. if (backgroundSubstractor != null)
  92. backgroundSubstractor.Dispose();
  93. switch (algorithm)
  94. {
  95. case BackgroundSubtractorAlgorithmPreset.KNN:
  96. backgroundSubstractor = Video.createBackgroundSubtractorKNN();
  97. //BackgroundSubtractorKNN subtractorKNN = (BackgroundSubtractorKNN)backgroundSubstractor;
  98. //subtractorKNN.setDetectShadows(true);
  99. //subtractorKNN.setDist2Threshold(400);
  100. //subtractorKNN.setHistory(500);
  101. //subtractorKNN.setkNNSamples(2);
  102. //subtractorKNN.setNSamples(7);
  103. //subtractorKNN.setShadowThreshold(0.5);
  104. //subtractorKNN.setShadowValue(127);
  105. break;
  106. case BackgroundSubtractorAlgorithmPreset.MOG2:
  107. backgroundSubstractor = Video.createBackgroundSubtractorMOG2();
  108. //BackgroundSubtractorMOG2 subtractorMOG2 = (BackgroundSubtractorMOG2)backgroundSubstractor;
  109. //subtractorMOG2.setBackgroundRatio(0.899999976158142);
  110. //subtractorMOG2.setComplexityReductionThreshold(0.0500000007450581);
  111. //subtractorMOG2.setDetectShadows(true);
  112. //subtractorMOG2.setHistory(500);
  113. //subtractorMOG2.setNMixtures(5);
  114. //subtractorMOG2.setShadowThreshold(0.5);
  115. //subtractorMOG2.setShadowValue(127);
  116. //subtractorMOG2.setVarInit(15);
  117. //subtractorMOG2.setVarMax(75);
  118. //subtractorMOG2.setVarMin(4);
  119. //subtractorMOG2.setVarThreshold(16);
  120. //subtractorMOG2.setVarThresholdGen(9);
  121. break;
  122. case BackgroundSubtractorAlgorithmPreset.CNT:
  123. backgroundSubstractor = Bgsegm.createBackgroundSubtractorCNT();
  124. //BackgroundSubtractorCNT subtractorCNT = (BackgroundSubtractorCNT)backgroundSubstractor;
  125. //subtractorCNT.setIsParallel(true);
  126. //subtractorCNT.setMaxPixelStability(900)
  127. //subtractorCNT.setMinPixelStability(15);
  128. //subtractorCNT.setUseHistory(true);
  129. break;
  130. case BackgroundSubtractorAlgorithmPreset.GMG:
  131. backgroundSubstractor = Bgsegm.createBackgroundSubtractorGMG();
  132. break;
  133. case BackgroundSubtractorAlgorithmPreset.GSOC:
  134. backgroundSubstractor = Bgsegm.createBackgroundSubtractorGSOC();
  135. break;
  136. case BackgroundSubtractorAlgorithmPreset.LSBP:
  137. backgroundSubstractor = Bgsegm.createBackgroundSubtractorLSBP();
  138. break;
  139. case BackgroundSubtractorAlgorithmPreset.MOG:
  140. backgroundSubstractor = Bgsegm.createBackgroundSubtractorMOG();
  141. break;
  142. default:
  143. break;
  144. }
  145. }
  146. /// <summary>
  147. /// Raises the video capture to mat helper initialized event.
  148. /// </summary>
  149. public void OnVideoCaptureToMatHelperInitialized()
  150. {
  151. Debug.Log("OnVideoCaptureToMatHelperInitialized");
  152. Mat rgbMat = sourceToMatHelper.GetMat();
  153. texture = new Texture2D(rgbMat.cols(), rgbMat.rows(), TextureFormat.RGB24, false);
  154. Utils.matToTexture2D(rgbMat, texture);
  155. gameObject.GetComponent<Renderer>().material.mainTexture = texture;
  156. gameObject.transform.localScale = new Vector3(rgbMat.cols(), rgbMat.rows(), 1);
  157. Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
  158. float width = rgbMat.width();
  159. float height = rgbMat.height();
  160. float widthScale = (float)Screen.width / width;
  161. float heightScale = (float)Screen.height / height;
  162. if (widthScale < heightScale)
  163. {
  164. Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
  165. }
  166. else
  167. {
  168. Camera.main.orthographicSize = height / 2;
  169. }
  170. fgmaskMat = new Mat(rgbMat.rows(), rgbMat.cols(), CvType.CV_8UC1);
  171. }
  172. /// <summary>
  173. /// Raises the video capture to mat helper disposed event.
  174. /// </summary>
  175. public void OnVideoCaptureToMatHelperDisposed()
  176. {
  177. Debug.Log("OnVideoCaptureToMatHelperDisposed");
  178. if (backgroundSubstractor != null)
  179. backgroundSubstractor.clear();
  180. if (fgmaskMat != null)
  181. fgmaskMat.Dispose();
  182. if (texture != null)
  183. {
  184. Texture2D.Destroy(texture);
  185. texture = null;
  186. }
  187. }
  188. /// <summary>
  189. /// Raises the video capture to mat helper error occurred event.
  190. /// </summary>
  191. /// <param name="errorCode">Error code.</param>
  192. public void OnVideoCaptureToMatHelperErrorOccurred(VideoCaptureToMatHelper.ErrorCode errorCode)
  193. {
  194. Debug.Log("OnVideoCaptureToMatHelperErrorOccurred " + errorCode);
  195. if (fpsMonitor != null)
  196. {
  197. fpsMonitor.consoleText = "ErrorCode: " + errorCode;
  198. }
  199. }
  200. // Update is called once per frame
  201. void Update()
  202. {
  203. if (sourceToMatHelper.IsPlaying() && sourceToMatHelper.DidUpdateThisFrame())
  204. {
  205. Mat rgbMat = sourceToMatHelper.GetMat();
  206. watch.Reset();
  207. watch.Start();
  208. backgroundSubstractor.apply(rgbMat, fgmaskMat);
  209. if (enableMorphologyExToggle.isOn)
  210. Imgproc.morphologyEx(fgmaskMat, fgmaskMat, Imgproc.MORPH_OPEN, kernel);
  211. watch.Stop();
  212. if (showBackgroundImageToggle.isOn && backgroundSubtractorAlgorithm != BackgroundSubtractorAlgorithmPreset.GMG)
  213. {
  214. if (backgroundSubtractorAlgorithm == BackgroundSubtractorAlgorithmPreset.CNT)
  215. {
  216. backgroundSubstractor.getBackgroundImage(fgmaskMat);
  217. Imgproc.cvtColor(fgmaskMat, rgbMat, Imgproc.COLOR_GRAY2RGB);
  218. }
  219. else
  220. {
  221. backgroundSubstractor.getBackgroundImage(rgbMat);
  222. }
  223. }
  224. else
  225. {
  226. Imgproc.cvtColor(fgmaskMat, rgbMat, Imgproc.COLOR_GRAY2RGB);
  227. }
  228. Utils.matToTexture2D(rgbMat, texture);
  229. if (fpsMonitor != null)
  230. {
  231. fpsMonitor.Add("time: ", watch.ElapsedMilliseconds + " ms");
  232. }
  233. }
  234. }
  235. /// <summary>
  236. /// Raises the destroy event.
  237. /// </summary>
  238. void OnDestroy()
  239. {
  240. if (backgroundSubstractor != null)
  241. backgroundSubstractor.Dispose();
  242. if (sourceToMatHelper != null)
  243. sourceToMatHelper.Dispose();
  244. }
  245. /// <summary>
  246. /// Raises the back button click event.
  247. /// </summary>
  248. public void OnBackButtonClick()
  249. {
  250. SceneManager.LoadScene("OpenCVForUnityExample");
  251. }
  252. /// <summary>
  253. /// Raises the background subtractor algorithm dropdown value changed event.
  254. /// </summary>
  255. public void OnBackgroundSubtractorAlgorithmDropdownValueChanged(int result)
  256. {
  257. string[] enumNames = Enum.GetNames(typeof(BackgroundSubtractorAlgorithmPreset));
  258. byte value = (byte)System.Enum.Parse(typeof(BackgroundSubtractorAlgorithmPreset), enumNames[result], true);
  259. if ((byte)backgroundSubtractorAlgorithm != value)
  260. {
  261. backgroundSubtractorAlgorithm = (BackgroundSubtractorAlgorithmPreset)value;
  262. }
  263. //Debug.Log((int)backgroundSubtractorAlgorithm);
  264. CreateBackgroundSubstractor(backgroundSubtractorAlgorithm);
  265. sourceToMatHelper.Initialize();
  266. }
  267. /// <summary>
  268. /// Raises the enable MorphologyEx toggle value changed event.
  269. /// </summary>
  270. public void OnEnableMorphologyExToggleValueChanged()
  271. {
  272. //
  273. //Debug.Log(enableMorphologyExToggleToggle.isOn);
  274. }
  275. /// <summary>
  276. /// Raises the show background image toggle value changed event.
  277. /// </summary>
  278. public void OnShowBackgroundImageToggleValueChanged()
  279. {
  280. //
  281. //Debug.Log(showBackgroundImageToggle.isOn);
  282. }
  283. public enum BackgroundSubtractorAlgorithmPreset : byte
  284. {
  285. KNN = 0,
  286. MOG2,
  287. CNT,
  288. GMG,
  289. GSOC,
  290. LSBP,
  291. MOG,
  292. }
  293. }
  294. }