Utils.cs 67 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281
  1. using UnityEngine;
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using System.Runtime.InteropServices;
  6. using System.IO;
  7. using AOT;
  8. using OpenCVForUnity.CoreModule;
  9. namespace OpenCVForUnity.UnityUtils
  10. {
  11. public static class Utils
  12. {
  13. /**
  14. * Returns this "OpenCV for Unity" version number.
  15. *
  16. * @return this "OpenCV for Unity" version number
  17. */
  18. public static string getVersion ()
  19. {
  20. return "2.3.3";
  21. }
  22. /**
  23. * Copies OpenCV Mat data to Pixel Data IntPtr.
  24. * <p>
  25. * <br>This function copies the OpenCV Mat data to the pixel data IntPtr.
  26. * <br>The pixel data has to be of the same byte size as the Mat data ([total() * elemSize()] byte).
  27. * <br>Because this function doesn't check bounds, is faster than Mat.get().
  28. *
  29. * @param mat a Mat object.
  30. * @param intPtr the pixel data has to be of the same byte size as the Mat data ([total() * elemSize()] byte).
  31. */
  32. public static void copyFromMat (Mat mat, IntPtr intPtr)
  33. {
  34. if (mat != null)
  35. mat.ThrowIfDisposed ();
  36. if (mat == null)
  37. throw new ArgumentNullException ("mat == null");
  38. if (intPtr == IntPtr.Zero)
  39. throw new ArgumentNullException ("intPtr == IntPtr.Zero");
  40. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  41. OpenCVForUnity_MatDataToByteArray (mat.nativeObj, intPtr);
  42. #else
  43. return;
  44. #endif
  45. }
  46. /**
  47. * Copies Pixel Data IntPtr to OpenCV Mat data.
  48. * <p>
  49. * <br>This function copy the pixel data IntPtr to the OpenCV Mat data.
  50. * <br>The Mat object has to be of the same byte size as the pixel data ([total() * elemSize()] byte).
  51. * <br>Because this function doesn't check bounds, is faster than Mat.put().
  52. *
  53. * @param intPtr a pixel data IntPtr.
  54. * @param mat the Mat object has to be of the same byte size as the pixel data ([total() * elemSize()] byte).
  55. */
  56. public static void copyToMat (IntPtr intPtr, Mat mat)
  57. {
  58. if (mat != null)
  59. mat.ThrowIfDisposed ();
  60. if (intPtr == IntPtr.Zero)
  61. throw new ArgumentNullException ("intPtr == IntPtr.Zero");
  62. if (mat == null)
  63. throw new ArgumentNullException ("mat == null");
  64. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  65. OpenCVForUnity_ByteArrayToMatData (intPtr, mat.nativeObj);
  66. #else
  67. return;
  68. #endif
  69. }
  70. /**
  71. * Copies OpenCV Mat data to Pixel Data Array.
  72. * <p>
  73. * <br>This function copies the OpenCV Mat data to the pixel data Array.
  74. * <br>The pixel data Array has to be of the same byte size as the Mat data ([total() * elemSize()] byte).
  75. * <br>Because this function doesn't check bounds, is faster than Mat.get().
  76. *
  77. * @param mat a Mat object.
  78. * @param array the pixel data Array has to be of the same byte size as the Mat data ([total() * elemSize()] byte).
  79. */
  80. public static void copyFromMat<T> (Mat mat, IList<T> array)
  81. {
  82. if (mat != null)
  83. mat.ThrowIfDisposed ();
  84. if (mat == null)
  85. throw new ArgumentNullException ("mat == null");
  86. if (array == null)
  87. throw new ArgumentNullException ("array == null");
  88. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  89. GCHandle arrayHandle = GCHandle.Alloc (array, GCHandleType.Pinned);
  90. OpenCVForUnity_MatDataToByteArray (mat.nativeObj, arrayHandle.AddrOfPinnedObject ());
  91. arrayHandle.Free ();
  92. #else
  93. return;
  94. #endif
  95. }
  96. /**
  97. * Copies Pixel Data Array to OpenCV Mat data.
  98. * <p>
  99. * <br>This function copies the pixel data Array to the OpenCV Mat data.
  100. * <br>The Mat object has to be of the same byte size as the pixel data Array ([total() * elemSize()] byte).
  101. * <br>Because this function doesn't check bounds, is faster than Mat.put().
  102. *
  103. * @param array a pixel data Array.
  104. * @param mat the Mat object has to be of the same byte size as the pixel data Array ([total() * elemSize()] byte).
  105. */
  106. public static void copyToMat<T> (IList<T> array, Mat mat)
  107. {
  108. if (mat != null)
  109. mat.ThrowIfDisposed ();
  110. if (array == null)
  111. throw new ArgumentNullException ("array == null");
  112. if (mat == null)
  113. throw new ArgumentNullException ("mat == null");
  114. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  115. GCHandle arrayHandle = GCHandle.Alloc (array, GCHandleType.Pinned);
  116. OpenCVForUnity_ByteArrayToMatData (arrayHandle.AddrOfPinnedObject (), mat.nativeObj);
  117. arrayHandle.Free ();
  118. #else
  119. return;
  120. #endif
  121. }
  122. /**
  123. * Converts OpenCV Mat to Unity Texture2D.
  124. * <p>
  125. * <br>This function converts the OpenCV Mat to the Unity Texture2D image.
  126. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  127. * <br>The Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function.)
  128. * <br>The Texture2D object has to be of the same size as the Mat (width * height).
  129. *
  130. * @param mat the Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY)
  131. * @param texture2D the Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function.) The Texture2D object has to be of the same size as the Mat (width * height).
  132. * @param flip if true, the mat is fliped before converting.
  133. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  134. * @param flipAfter if true, the mat is fliped after converting. If you want to use mat even after calling this function, set true.
  135. * @param updateMipmaps When set to true, mipmap levels are recalculated.
  136. * @param makeNoLongerReadable When set to true, system memory copy of a texture is released.
  137. */
  138. public static void matToTexture2D (Mat mat, Texture2D texture2D, bool flip = true, int flipCode = 0, bool flipAfter = false, bool updateMipmaps = false, bool makeNoLongerReadable = false)
  139. {
  140. matToTexture2D (mat, texture2D, null, flip, flipCode, flipAfter, updateMipmaps, makeNoLongerReadable);
  141. }
  142. /**
  143. * Converts OpenCV Mat to Unity Texture2D.
  144. * <p>
  145. * <br>This function converts the OpenCV Mat to the Unity Texture2D image.
  146. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  147. * <br>The Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function.)
  148. * <br>The Texture2D object has to be of the same size as the Mat (width * height).
  149. *
  150. * @param mat the Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY)
  151. * @param texture2D the Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function) The Texture2D object has to be of the same size as the Mat (width * height).
  152. * @param bufferColors the optional array to receive pixel data.
  153. * You can optionally pass in an array of Color32s to use in colors to avoid allocating new memory each frame.
  154. * The array needs to be initialized to a length matching width * height of the texture. (<a href="http://docs.unity3d.com/ScriptReference/WebCamTexture.GetPixels32.html">http://docs.unity3d.com/ScriptReference/WebCamTexture.GetPixels32.html</a>)
  155. * @param flip if true, the mat is fliped before converting.
  156. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  157. * @param flipAfter if true, the mat is fliped after converting. If you want to use mat even after calling this function, set true.
  158. * @param updateMipmaps When set to true, mipmap levels are recalculated.
  159. * @param makeNoLongerReadable When set to true, system memory copy of a texture is released.
  160. */
  161. public static void matToTexture2D (Mat mat, Texture2D texture2D, Color32[] bufferColors, bool flip = true, int flipCode = 0, bool flipAfter = false, bool updateMipmaps = false, bool makeNoLongerReadable = false)
  162. {
  163. if (mat != null)
  164. mat.ThrowIfDisposed ();
  165. if (mat == null)
  166. throw new ArgumentNullException ("mat == null");
  167. if (texture2D == null)
  168. throw new ArgumentNullException ("texture2D == null");
  169. if (mat.cols () != texture2D.width || mat.rows () != texture2D.height)
  170. throw new ArgumentException ("The Texture2D object has to be of the same size");
  171. // Core.flip (mat, mat, 0);
  172. //
  173. // byte[] data = new byte[mat.cols () * mat.rows () * mat.channels ()];
  174. // mat.get (0, 0, data);
  175. //
  176. // Core.flip (mat, mat, 0);
  177. //
  178. // if (texture2D.format == TextureFormat.ARGB32 || texture2D.format == TextureFormat.BGRA32 || texture2D.format == TextureFormat.RGBA32) {
  179. //
  180. // Color32[] colors = new Color32[mat.cols () * mat.rows ()];
  181. //
  182. //
  183. //
  184. // if (mat.type () == CvType.CV_8UC1) {
  185. // for (int i = 0; i < colors.Length; i++) {
  186. // colors [i] = new Color32 (data [i], data [i], data [i], 255);
  187. // }
  188. // } else if (mat.type () == CvType.CV_8UC3) {
  189. // for (int i = 0; i < colors.Length; i++) {
  190. // colors [i] = new Color32 (data [(i * 3) + 0], data [(i * 3) + 1], data [(i * 3) + 2], 255);
  191. // }
  192. // } else if (mat.type () == CvType.CV_8UC4) {
  193. // for (int i = 0; i < colors.Length; i++) {
  194. // colors [i] = new Color32 (data [(i * 4) + 0], data [(i * 4) + 1], data [(i * 4) + 2], data [(i * 4) + 3]);
  195. // }
  196. // }
  197. //
  198. //
  199. // texture2D.SetPixels32 (colors);
  200. //
  201. // } else {
  202. // Color[] colors = new Color[mat.cols () * mat.rows ()];
  203. //
  204. // if (mat.type () == CvType.CV_8UC1) {
  205. // for (int i = 0; i < colors.Length; i++) {
  206. // colors [i] = new Color ((float)data [i] / 255.0f, data [i] / 255.0f, data [i] / 255.0f);
  207. // }
  208. // } else if (mat.type () == CvType.CV_8UC3) {
  209. // for (int i = 0; i < colors.Length; i++) {
  210. // colors [i] = new Color ((float)data [(i * 3) + 0] / 255.0f, (float)data [(i * 3) + 1] / 255.0f, (float)data [(i * 3) + 2] / 255.0f);
  211. // }
  212. // } else if (mat.type () == CvType.CV_8UC4) {
  213. // for (int i = 0; i < colors.Length; i++) {
  214. // colors [i] = new Color ((float)data [(i * 4) + 0] / 255.0f, (float)data [(i * 4) + 1] / 255.0f, (float)data [(i * 4) + 2] / 255.0f);
  215. // }
  216. // }
  217. //
  218. //
  219. // texture2D.SetPixels (colors);
  220. //
  221. // }
  222. //
  223. // texture2D.Apply ();
  224. // #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  225. // if(mat.type () == CvType.CV_8UC4){
  226. // OpenCVForUnity_LowLevelMatToTexture (mat.nativeObj, texture2D.GetNativeTexturePtr(), texture2D.width, texture2D.height);
  227. //
  228. // return;
  229. // }
  230. //
  231. // #endif
  232. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  233. #if UNITY_5_3_OR_NEWER
  234. int type = mat.type ();
  235. if (mat.isContinuous () && (texture2D.format == TextureFormat.RGBA32 && type == CvType.CV_8UC4) || (texture2D.format == TextureFormat.RGB24 && type == CvType.CV_8UC3) || (texture2D.format == TextureFormat.Alpha8 && type == CvType.CV_8UC1)) {
  236. if (flip) {
  237. Core.flip (mat, mat, flipCode);
  238. }
  239. texture2D.LoadRawTextureData ((IntPtr)mat.dataAddr (), (int)mat.total () * (int)mat.elemSize ());
  240. texture2D.Apply (updateMipmaps, makeNoLongerReadable);
  241. if (flipAfter) {
  242. Core.flip (mat, mat, flipCode);
  243. }
  244. return;
  245. }
  246. #endif
  247. GCHandle colorsHandle;
  248. if (bufferColors == null) {
  249. Color32[] colors = texture2D.GetPixels32 ();
  250. colorsHandle = GCHandle.Alloc (colors, GCHandleType.Pinned);
  251. OpenCVForUnity_MatToTexture (mat.nativeObj, colorsHandle.AddrOfPinnedObject (), flip, flipCode, flipAfter);
  252. texture2D.SetPixels32 (colors);
  253. } else {
  254. colorsHandle = GCHandle.Alloc (bufferColors, GCHandleType.Pinned);
  255. OpenCVForUnity_MatToTexture (mat.nativeObj, colorsHandle.AddrOfPinnedObject (), flip, flipCode, flipAfter);
  256. texture2D.SetPixels32 (bufferColors);
  257. }
  258. texture2D.Apply (updateMipmaps, makeNoLongerReadable);
  259. colorsHandle.Free ();
  260. #else
  261. return;
  262. #endif
  263. }
  264. /**
  265. * Fast converts OpenCV Mat to Unity Texture2D. (Unity5.3+)
  266. * <p>
  267. * <br>This function converts the OpenCV Mat to the Unity Texture2D image.
  268. * <br>Passed Mat data should be of required size to fill the whole texture according to its width, height, data format and mipmapCount.
  269. * <br>This function doesn't check bounds.
  270. *
  271. * @param mat
  272. * @param texture2D The Texture2D object has to be of the same size as the Mat (width * height).
  273. * @param flip if true, the mat is fliped before converting.
  274. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  275. * @param flipAfter if true, the mat is fliped after converting. If you want to use mat even after calling this function, set true.
  276. * @param updateMipmaps When set to true, mipmap levels are recalculated.
  277. * @param makeNoLongerReadable When set to true, system memory copy of a texture is released.
  278. */
  279. public static void fastMatToTexture2D (Mat mat, Texture2D texture2D, bool flip = true, int flipCode = 0, bool flipAfter = false, bool updateMipmaps = false, bool makeNoLongerReadable = false)
  280. {
  281. if (mat != null)
  282. mat.ThrowIfDisposed ();
  283. if (mat == null)
  284. throw new ArgumentNullException ("mat == null");
  285. if (texture2D == null)
  286. throw new ArgumentNullException ("texture2D == null");
  287. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  288. #if UNITY_5_3_OR_NEWER
  289. if (!mat.isContinuous ()) {
  290. throw new ArgumentException ("mat.isContinuous() must be true.");
  291. }
  292. if (flip) {
  293. Core.flip (mat, mat, flipCode);
  294. }
  295. texture2D.LoadRawTextureData ((IntPtr)mat.dataAddr (), (int)mat.total () * (int)mat.elemSize ());
  296. texture2D.Apply (updateMipmaps, makeNoLongerReadable);
  297. if (flipAfter) {
  298. Core.flip (mat, mat, flipCode);
  299. }
  300. return;
  301. #else
  302. return;
  303. #endif
  304. #else
  305. return;
  306. #endif
  307. }
  308. /**
  309. * Converts Unity Texture2D to OpenCV Mat.
  310. * <p>
  311. * <br>This function converts the Unity Texture2D image to the OpenCV Mat.
  312. * <br>The Mat object has to be of the same size as the Texture2D (width * height).
  313. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  314. *
  315. * @param texture2D the Texture2D object has to be of the TextureFormat 'RGBA32' or 'ARGB32'. (SetPixels32() must function)
  316. * @param mat the Mat object has to be of the same size as the Texture2D (width * height).
  317. * The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  318. * @param flip if true, the mat is fliped after converting.
  319. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  320. */
  321. public static void texture2DToMat (Texture2D texture2D, Mat mat, bool flip = true, int flipCode = 0)
  322. {
  323. if (mat != null)
  324. mat.ThrowIfDisposed ();
  325. if (texture2D == null)
  326. throw new ArgumentNullException ("texture2D == null");
  327. if (mat == null)
  328. throw new ArgumentNullException ("mat == null");
  329. if (mat.cols () != texture2D.width || mat.rows () != texture2D.height)
  330. throw new ArgumentException ("The Mat object has to be of the same size");
  331. // byte[] data = new byte[mat.cols () * mat.rows () * mat.channels ()];
  332. //
  333. // Color32[] colors = texture2D.GetPixels32 ();
  334. //
  335. // if (mat.type () == CvType.CV_8UC1) {
  336. // for (int i = 0; i < colors.Length; i++) {
  337. // data [i] = colors [i].b;
  338. // }
  339. // mat.put (0, 0, data);
  340. // Core.flip (mat, mat, 0);
  341. // } else if (mat.type () == CvType.CV_8UC3) {
  342. // for (int i = 0; i < colors.Length; i++) {
  343. // data [(i * 3) + 0] = colors [i].b;
  344. // data [(i * 3) + 1] = colors [i].g;
  345. // data [(i * 3) + 2] = colors [i].r;
  346. // }
  347. // mat.put (0, 0, data);
  348. // Core.flip (mat, mat, 0);
  349. // } else if (mat.type () == CvType.CV_8UC4) {
  350. // for (int i = 0; i < colors.Length; i++) {
  351. // data [(i * 4) + 0] = colors [i].b;
  352. // data [(i * 4) + 1] = colors [i].g;
  353. // data [(i * 4) + 2] = colors [i].r;
  354. // data [(i * 4) + 3] = colors [i].a;
  355. // }
  356. // mat.put (0, 0, data);
  357. // Core.flip (mat, mat, 0);
  358. // }
  359. // #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  360. // if(mat.type () == CvType.CV_8UC4){
  361. // OpenCVForUnity_LowLevelTextureToMat (texture2D.GetNativeTexturePtr(), texture2D.width, texture2D.height, mat.nativeObj);
  362. //
  363. // return;
  364. // }
  365. //
  366. // #endif
  367. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  368. #if (UNITY_5 && !UNITY_5_0) || UNITY_5_3_OR_NEWER
  369. int type = mat.type ();
  370. if ((texture2D.format == TextureFormat.RGBA32 && type == CvType.CV_8UC4) || (texture2D.format == TextureFormat.RGB24 && type == CvType.CV_8UC3) || (texture2D.format == TextureFormat.Alpha8 && type == CvType.CV_8UC1)) {
  371. mat.put (0, 0, texture2D.GetRawTextureData ());
  372. if (flip) {
  373. Core.flip (mat, mat, flipCode);
  374. }
  375. return;
  376. }
  377. #endif
  378. Color32[] colors = texture2D.GetPixels32 ();
  379. GCHandle colorsHandle = GCHandle.Alloc (colors, GCHandleType.Pinned);
  380. OpenCVForUnity_TextureToMat (colorsHandle.AddrOfPinnedObject (), mat.nativeObj, flip, flipCode);
  381. colorsHandle.Free ();
  382. #else
  383. return;
  384. #endif
  385. }
  386. /**
  387. * Fast converts Unity Texture2D to OpenCV Mat. (Unity5.1+)
  388. * <p>
  389. * <br>This function converts the Unity Texture2D image to the OpenCV Mat.
  390. * <br>Mat data size must be the same as the texture data size.
  391. * <br>This function doesn't check bounds.
  392. *
  393. * @param texture2D
  394. * @param mat the Mat object has to be of the same size as the Texture2D (width * height).
  395. * @param flip if true, the mat is fliped after converting.
  396. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  397. */
  398. public static void fastTexture2DToMat (Texture2D texture2D, Mat mat, bool flip = true, int flipCode = 0)
  399. {
  400. if (mat != null)
  401. mat.ThrowIfDisposed ();
  402. if (texture2D == null)
  403. throw new ArgumentNullException ("texture2D == null");
  404. if (mat == null)
  405. throw new ArgumentNullException ("mat == null");
  406. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  407. #if (UNITY_5 && !UNITY_5_0) || UNITY_5_3_OR_NEWER
  408. Utils.copyToMat (texture2D.GetRawTextureData (), mat);
  409. if (flip) {
  410. Core.flip (mat, mat, flipCode);
  411. }
  412. return;
  413. #else
  414. return;
  415. #endif
  416. #else
  417. return;
  418. #endif
  419. }
  420. /**
  421. * Converts Unity WebCamTexture to OpenCV Mat.
  422. * <p>
  423. * <br>This function converts the Unity WebCamTexture image to the OpenCV Mat.
  424. * <br>The Mat object has to be of the same size as the WebCamTexture (width * height).
  425. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  426. *
  427. * @param webcamTexture a WebCamTexture object.
  428. * @param mat the Mat object has to be of the same size as the WebCamTexture (width * height).
  429. * The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  430. * @param flip if true, the mat is fliped after converting.
  431. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  432. */
  433. public static void webCamTextureToMat (WebCamTexture webCamTexture, Mat mat, bool flip = true, int flipCode = 0)
  434. {
  435. webCamTextureToMat (webCamTexture, mat, null, flip, flipCode);
  436. }
  437. /**
  438. * Converts Unity WebCamTexture to OpenCV Mat.
  439. * <p>
  440. * <br>This function converts the Unity WebCamTexture image to the OpenCV Mat.
  441. * <br>The Mat object has to be of the same size as the WebCamTexture (width * height).
  442. * <br>The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  443. *
  444. * @param webcamTexture a WebCamTexture object.
  445. * @param mat the Mat object has to be of the same size as the WebCamTexture' (width * height).
  446. * The Mat object has to be of the types 'CV_8UC4' (RGBA) , 'CV_8UC3' (RGB) or 'CV_8UC1' (GRAY).
  447. * @param bufferColors the optional array to receive pixel data.
  448. * You can optionally pass in an array of Color32s to use in colors to avoid allocating new memory each frame.
  449. * The array needs to be initialized to a length matching width * height of the texture. (http://docs.unity3d.com/ScriptReference/WebCamTexture.GetPixels32.html)
  450. * @param flip if true, the mat is fliped after converting.
  451. * @param flipCode a flag to specify how to flip the array; 0 means flipping around the x-axis and positive value (for example, 1) means flipping around y-axis. Negative value (for example, -1) means flipping around both axes.
  452. */
  453. public static void webCamTextureToMat (WebCamTexture webCamTexture, Mat mat, Color32[] bufferColors, bool flip = true, int flipCode = 0)
  454. {
  455. if (mat != null)
  456. mat.ThrowIfDisposed ();
  457. if (webCamTexture == null)
  458. throw new ArgumentNullException ("webCamTexture == null");
  459. if (mat == null)
  460. throw new ArgumentNullException ("mat == null");
  461. if (mat.cols () != webCamTexture.width || mat.rows () != webCamTexture.height)
  462. throw new ArgumentException ("The Mat object has to be of the same size");
  463. // byte[] data = new byte[mat.cols () * mat.rows () * mat.channels ()];
  464. //
  465. // Color32[] colors = webCamTexture.GetPixels32 ();
  466. //
  467. // if (mat.type () == CvType.CV_8UC1) {
  468. // for (int i = 0; i < colors.Length; i++) {
  469. // data [i] = colors [i].b;
  470. // }
  471. // mat.put (0, 0, data);
  472. // Core.flip (mat, mat, 0);
  473. // } else if (mat.type () == CvType.CV_8UC3) {
  474. // for (int i = 0; i < colors.Length; i++) {
  475. // data [(i * 3) + 0] = colors [i].r;
  476. // data [(i * 3) + 1] = colors [i].g;
  477. // data [(i * 3) + 2] = colors [i].b;
  478. // }
  479. // mat.put (0, 0, data);
  480. // Core.flip (mat, mat, 0);
  481. // } else if (mat.type () == CvType.CV_8UC4) {
  482. // for (int i = 0; i < colors.Length; i++) {
  483. // data [(i * 4) + 0] = colors [i].r;
  484. // data [(i * 4) + 1] = colors [i].g;
  485. // data [(i * 4) + 2] = colors [i].b;
  486. // data [(i * 4) + 3] = colors [i].a;
  487. // }
  488. // mat.put (0, 0, data);
  489. // Core.flip (mat, mat, 0);
  490. // }
  491. // #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  492. // if(mat.type () == CvType.CV_8UC4){
  493. // OpenCVForUnity_LowLevelTextureToMat (webCamTexture.GetNativeTexturePtr(), webCamTexture.width, webCamTexture.height, mat.nativeObj);
  494. //
  495. // return;
  496. // }
  497. //
  498. // #endif
  499. #if (UNITY_IOS && !UNITY_EDITOR && (UNITY_4_6_3 || UNITY_5_0_0 || UNITY_5_0_1))
  500. if (mat.type () == CvType.CV_8UC4) {
  501. OpenCVForUnity_LowLevelTextureToMat (webCamTexture.GetNativeTexturePtr (), webCamTexture.width, webCamTexture.height, mat.nativeObj);
  502. if (Utils.getLowLevelGraphicsDeviceType() == 16 && Utils.getLowLevelTextureFormat (webCamTexture) == 80) {
  503. Imgproc.cvtColor (mat, mat, Imgproc.COLOR_BGRA2RGBA);
  504. }
  505. Core.flip (mat, mat, 0);
  506. return;
  507. }
  508. #endif
  509. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  510. GCHandle colorsHandle;
  511. if (bufferColors == null) {
  512. Color32[] colors = webCamTexture.GetPixels32 ();
  513. colorsHandle = GCHandle.Alloc (colors, GCHandleType.Pinned);
  514. } else {
  515. webCamTexture.GetPixels32 (bufferColors);
  516. colorsHandle = GCHandle.Alloc (bufferColors, GCHandleType.Pinned);
  517. }
  518. OpenCVForUnity_TextureToMat (colorsHandle.AddrOfPinnedObject (), mat.nativeObj, flip, flipCode);
  519. colorsHandle.Free ();
  520. #else
  521. return;
  522. #endif
  523. }
  524. /**
  525. * Converts Texture to Texture2D.
  526. * <p>
  527. * <br>This function converts the Texture image to the Texture2D image.
  528. * <br>The texture and texture2D need to be the same size.
  529. * <br>The texture2D's TextureFormat needs to be RGBA32 (Unity5.5+), ARGB32, RGB24, RGBAFloat or RGBAHalf.
  530. *
  531. * @param texture a texture object.
  532. * @param texture2D a texture2D object.
  533. */
  534. public static void textureToTexture2D (Texture texture, Texture2D texture2D)
  535. {
  536. if (texture == null)
  537. throw new ArgumentNullException ("texture == null");
  538. if (texture2D == null)
  539. throw new ArgumentNullException ("texture2D == null");
  540. if (texture.width != texture2D.width || texture.height != texture2D.height)
  541. throw new ArgumentException ("texture and texture2D need to be the same size.");
  542. RenderTexture prevRT = RenderTexture.active;
  543. if (texture is RenderTexture) {
  544. RenderTexture.active = (RenderTexture)texture;
  545. texture2D.ReadPixels (new UnityEngine.Rect (0f, 0f, texture.width, texture.height), 0, 0, false);
  546. texture2D.Apply (false, false);
  547. } else {
  548. RenderTexture tempRT = RenderTexture.GetTemporary (texture.width, texture.height, 0, RenderTextureFormat.ARGB32);
  549. Graphics.Blit (texture, tempRT);
  550. RenderTexture.active = tempRT;
  551. texture2D.ReadPixels (new UnityEngine.Rect (0f, 0f, texture.width, texture.height), 0, 0, false);
  552. texture2D.Apply (false, false);
  553. RenderTexture.ReleaseTemporary (tempRT);
  554. }
  555. RenderTexture.active = prevRT;
  556. }
  557. /**
  558. * Register Plugin on WebGL.
  559. * <p>
  560. * <br>For the WebGL platform, please call this method before calling IntPtrToTextureInRenderThread(), ArrayToTextureInRenderThread() and MatToTextureInRenderThread() methods.
  561. */
  562. public static void registerWebGLPlugin ()
  563. {
  564. #if UNITY_WEBGL && !UNITY_EDITOR
  565. if(isWebGLPluginRegistered)return;
  566. OpenCVForUnity_RegisterPlugin();
  567. isWebGLPluginRegistered = true;
  568. #endif
  569. }
  570. /**
  571. * Copies Pixel Data IntPtr to Texture at render thread.
  572. * <p>
  573. * <br>This function copies the pixel data IntPtr to Texture at render thread.
  574. * <br>The pixel data has to be of the same byte size as the Texture data ([width * height * 4] byte)
  575. * <br>The texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  576. *
  577. * @param intPtr the pixel data has to be of the same byte size as the Texture data ([width * height * 4] byte).
  578. * @param texture the texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  579. */
  580. public static void intPtrToTextureInRenderThread (IntPtr intPtr, Texture texture)
  581. {
  582. if (intPtr == IntPtr.Zero)
  583. throw new ArgumentNullException ("intPtr == IntPtr.Zero");
  584. if (texture == null)
  585. throw new ArgumentNullException ("texture == null");
  586. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  587. OpenCVForUnity_SetByteArrayFromUnity (intPtr, 0, 0, 0);
  588. OpenCVForUnity_SetTextureFromUnity (texture.GetNativeTexturePtr (), texture.width, texture.height, 4);
  589. GL.IssuePluginEvent (OpenCVForUnity_GetRenderEventFunc (), 1);
  590. #else
  591. return;
  592. #endif
  593. }
  594. /**
  595. * Copies Pixel Data Array to Texture at render thread.
  596. * <p>
  597. * <br>This function copies the pixel data Array to Texture at render thread.
  598. * <br>The pixel data Array has to be of the same byte size as the Texture data ([width * height * 4] byte)
  599. * <br>The texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  600. *
  601. * @param array the pixel data Array has to be of the same byte size as the Texture data ([width * height * 4] byte).
  602. * @param texture the texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  603. */
  604. public static void arrayToTextureInRenderThread<T> (IList<T> array, Texture texture)
  605. {
  606. if (array == null)
  607. throw new ArgumentNullException ("array == null");
  608. if (texture == null)
  609. throw new ArgumentNullException ("texture == null");
  610. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  611. GCHandle arrayHandle = GCHandle.Alloc (array, GCHandleType.Pinned);
  612. OpenCVForUnity_SetByteArrayFromUnity (arrayHandle.AddrOfPinnedObject (), 0, 0, 0);
  613. OpenCVForUnity_SetTextureFromUnity (texture.GetNativeTexturePtr (), texture.width, texture.height, 4);
  614. GL.IssuePluginEvent (OpenCVForUnity_GetRenderEventFunc (), 1);
  615. arrayHandle.Free ();
  616. #else
  617. return;
  618. #endif
  619. }
  620. /**
  621. * Copies OpenCV Mat data to Texture at render thread.
  622. * <p>
  623. * <br>This function copies the OpenCV Mat data to Texture at render thread.
  624. * <br>This method does not flip mat before copying mat to the texture.
  625. * <br>The OpenCV Mat data has to be of the same byte size as the Texture data ([width * height * 4] byte)
  626. * <br>The texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  627. *
  628. * @param mat the OpenCV Mat data has to be of the same byte size as the Texture data ([width * height * 4] byte).
  629. * @param texture the texture's TextureFormat needs to be 4byte per pixel (RGBA32(Unity5.5+), ARGB32).
  630. */
  631. public static void matToTextureInRenderThread (Mat mat, Texture texture)
  632. {
  633. if (mat != null)
  634. mat.ThrowIfDisposed ();
  635. if (mat == null)
  636. throw new ArgumentNullException ("mat == null");
  637. if (texture == null)
  638. throw new ArgumentNullException ("texture == null");
  639. if (mat.cols () != texture.width || mat.rows () != texture.height)
  640. throw new ArgumentException ("The Texture object has to be of the same size");
  641. #if UNITY_PRO_LICENSE || ((UNITY_ANDROID || UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR) || UNITY_5 || UNITY_5_3_OR_NEWER
  642. if (!mat.isContinuous ()) {
  643. throw new ArgumentException ("mat.isContinuous() must be true.");
  644. }
  645. OpenCVForUnity_SetByteArrayFromUnity ((IntPtr)mat.dataAddr (), mat.width (), mat.height (), (int)mat.elemSize ());
  646. OpenCVForUnity_SetTextureFromUnity (texture.GetNativeTexturePtr (), texture.width, texture.height, 4);
  647. GL.IssuePluginEvent (OpenCVForUnity_GetRenderEventFunc (), 1);
  648. #else
  649. return;
  650. #endif
  651. }
  652. /**
  653. * Gets the readable path of a file in the "StreamingAssets" folder.
  654. * <p>
  655. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  656. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  657. * <br>[WebGL] If the target file has not yet been copied to WebGL's virtual filesystem, you need to use getFilePathAsync() at first.
  658. *
  659. * @param filepath a relative file path starting from "StreamingAssets" folder.
  660. * @param refresh [Android] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  661. * @param timeout [Android 2017.1+] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  662. * @return returns a readable file path in case of success and returns empty in case of error.
  663. */
  664. public static string getFilePath (string filepath, bool refresh = false, int timeout = 0)
  665. {
  666. #if UNITY_ANDROID && !UNITY_EDITOR
  667. filepath = filepath.TrimStart (chTrims);
  668. string srcPath = Path.Combine (Application.streamingAssetsPath, filepath);
  669. string destPath = Path.Combine (Application.persistentDataPath, "opencvforunity");
  670. destPath = Path.Combine (destPath, filepath);
  671. if (!refresh && File.Exists (destPath))
  672. return destPath;
  673. #if UNITY_2017_1_OR_NEWER
  674. using (UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.Get (srcPath)) {
  675. request.timeout = timeout;
  676. #if UNITY_2018_2_OR_NEWER
  677. request.SendWebRequest ();
  678. #else
  679. request.Send ();
  680. #endif
  681. while (!request.isDone) {;}
  682. #if UNITY_2017_1_OR_NEWER
  683. if (request.isHttpError || request.isNetworkError) {
  684. #else
  685. if (request.isError) {
  686. #endif
  687. Debug.LogWarning (request.error);
  688. Debug.LogWarning (request.responseCode);
  689. return String.Empty;
  690. }
  691. //create Directory
  692. String dirPath = Path.GetDirectoryName (destPath);
  693. if (!Directory.Exists (dirPath))
  694. Directory.CreateDirectory (dirPath);
  695. File.WriteAllBytes (destPath, request.downloadHandler.data);
  696. }
  697. #else
  698. using (WWW request = new WWW (srcPath)) {
  699. while (!request.isDone) {;}
  700. if (!string.IsNullOrEmpty(request.error)) {
  701. Debug.LogWarning (request.error);
  702. return String.Empty;
  703. }
  704. //create Directory
  705. String dirPath = Path.GetDirectoryName (destPath);
  706. if (!Directory.Exists (dirPath))
  707. Directory.CreateDirectory (dirPath);
  708. File.WriteAllBytes (destPath, request.bytes);
  709. }
  710. #endif
  711. return destPath;
  712. #elif UNITY_WEBGL && !UNITY_EDITOR
  713. filepath = filepath.TrimStart (chTrims);
  714. string destPath = Path.Combine(Path.AltDirectorySeparatorChar.ToString(), "opencvforunity");
  715. destPath = Path.Combine(destPath, filepath);
  716. if (File.Exists(destPath)){
  717. return destPath;
  718. }else{
  719. return String.Empty;
  720. }
  721. #else
  722. filepath = filepath.TrimStart (chTrims);
  723. string destPath = Path.Combine (Application.streamingAssetsPath, filepath);
  724. if (File.Exists (destPath)) {
  725. return destPath;
  726. } else {
  727. return String.Empty;
  728. }
  729. #endif
  730. }
  731. /**
  732. * Gets the multiple readable paths of files in the "StreamingAssets" folder.
  733. * <p>
  734. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  735. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  736. * <br>[WebGL] If the target file has not yet been copied to WebGL's virtual filesystem, you need to use getFilePathAsync() at first.
  737. *
  738. * @param filepaths an array of relative file paths starting from the "StreamingAssets" folder.
  739. * @param refresh [Android] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  740. * @param timeout [Android 2017.1+] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  741. * @return returns an array of readable file paths.
  742. */
  743. public static string[] getMultipleFilePaths (string[] filepaths, bool refresh = false, int timeout = 0)
  744. {
  745. string[] result = new string[filepaths.Length];
  746. for (int i = 0; i < filepaths.Length; i++) {
  747. result [i] = getFilePath (filepaths [i], refresh, timeout);
  748. }
  749. return result;
  750. }
  751. /**
  752. * Gets the readable path of a file in the "StreamingAssets" folder by using coroutines.
  753. * <p>
  754. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  755. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  756. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  757. *
  758. * @param filepath a relative file path starting from the "StreamingAssets" folder.
  759. * @param completed a callback function that is called when the process is completed. Returns a readable file path in case of success and returns empty in case of error.
  760. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  761. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  762. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  763. */
  764. public static IEnumerator getFilePathAsync (string filepath, Action<string> completed, bool refresh = false, int timeout = 0)
  765. {
  766. return getFilePathAsync (filepath, completed, null, null, refresh, timeout);
  767. }
  768. /**
  769. * Gets the readable path of a file in the "StreamingAssets" folder by using coroutines.
  770. * <p>
  771. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  772. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  773. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  774. *
  775. * @param filepath a relative file path starting from the "StreamingAssets" folder.
  776. * @param completed a callback function that is called when the process is completed. Returns a readable file path in case of success and returns empty in case of error.
  777. * @param progressChanged a callback function that is called when the process is the progress. Returns the file path and a progress value (0.0 to 1.0).
  778. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  779. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  780. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  781. */
  782. public static IEnumerator getFilePathAsync (string filepath, Action<string> completed, Action<string, float> progressChanged, bool refresh = false, int timeout = 0)
  783. {
  784. return getFilePathAsync (filepath, completed, progressChanged, null, refresh, timeout);
  785. }
  786. /**
  787. * Gets the readable path of a file in the "StreamingAssets" folder by using coroutines.
  788. * <p>
  789. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  790. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  791. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  792. *
  793. * @param filepath a relative file path starting from the "StreamingAssets" folder.
  794. * @param completed a callback function that is called when the process is completed. Returns a readable file path in case of success and returns empty in case of error.
  795. * @param progressChanged a callback function that is called when the process is the progress. Returns the file path and a progress value (0.0 to 1.0).
  796. * @param errorOccurred a callback function that is called when the process is error occurred. Returns the file path and an error string and an error response code.
  797. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  798. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  799. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  800. */
  801. public static IEnumerator getFilePathAsync (string filepath, Action<string> completed, Action<string, float> progressChanged, Action<string, string, long> errorOccurred, bool refresh = false, int timeout = 0)
  802. {
  803. #if (UNITY_ANDROID || UNITY_WEBGL) && !UNITY_EDITOR
  804. filepath = filepath.TrimStart (chTrims);
  805. string srcPath = Path.Combine(Application.streamingAssetsPath, filepath);
  806. #if UNITY_ANDROID
  807. string destPath = Path.Combine(Application.persistentDataPath, "opencvforunity");
  808. #else
  809. string destPath = Path.Combine(Path.AltDirectorySeparatorChar.ToString(), "opencvforunity");
  810. #endif
  811. destPath = Path.Combine(destPath, filepath);
  812. if (!refresh && File.Exists(destPath)){
  813. if (progressChanged != null)
  814. progressChanged (filepath, 0);
  815. yield return null;
  816. if (progressChanged != null)
  817. progressChanged (filepath, 1);
  818. if (completed != null)
  819. completed (destPath);
  820. } else {
  821. #if UNITY_WEBGL || (UNITY_ANDROID && UNITY_2017_1_OR_NEWER)
  822. using (UnityEngine.Networking.UnityWebRequest request = UnityEngine.Networking.UnityWebRequest.Get (srcPath)) {
  823. request.timeout = timeout;
  824. #if UNITY_2018_2_OR_NEWER
  825. request.SendWebRequest ();
  826. #else
  827. request.Send ();
  828. #endif
  829. while (!request.isDone) {
  830. if (progressChanged != null)
  831. progressChanged (filepath, request.downloadProgress);
  832. yield return null;
  833. }
  834. if (progressChanged != null)
  835. progressChanged (filepath, request.downloadProgress);
  836. #if UNITY_2017_1_OR_NEWER
  837. if (request.isHttpError || request.isNetworkError) {
  838. #else
  839. if (request.isError) {
  840. #endif
  841. Debug.LogWarning (request.error);
  842. Debug.LogWarning (request.responseCode);
  843. if (errorOccurred != null) {
  844. errorOccurred (filepath, request.error, request.responseCode);
  845. } else {
  846. if (completed != null)
  847. completed (String.Empty);
  848. }
  849. yield break;
  850. }
  851. //create Directory
  852. String dirPath = Path.GetDirectoryName (destPath);
  853. if (!Directory.Exists (dirPath))
  854. Directory.CreateDirectory (dirPath);
  855. File.WriteAllBytes (destPath, request.downloadHandler.data);
  856. }
  857. #else
  858. using (WWW request = new WWW (srcPath)) {
  859. while (!request.isDone) {
  860. if (progressChanged != null)
  861. progressChanged(filepath, request.progress);
  862. yield return null;
  863. }
  864. if (progressChanged != null)
  865. progressChanged (filepath, request.progress);
  866. if (!string.IsNullOrEmpty(request.error)) {
  867. Debug.LogWarning (request.error);
  868. if (errorOccurred != null) {
  869. errorOccurred (filepath, request.error, 0);
  870. } else {
  871. if (completed != null)
  872. completed (String.Empty);
  873. }
  874. yield break;
  875. }
  876. //create Directory
  877. String dirPath = Path.GetDirectoryName (destPath);
  878. if (!Directory.Exists (dirPath))
  879. Directory.CreateDirectory (dirPath);
  880. File.WriteAllBytes(destPath, request.bytes);
  881. }
  882. #endif
  883. if (completed != null)
  884. completed (destPath);
  885. }
  886. #else
  887. filepath = filepath.TrimStart (chTrims);
  888. string destPath = Path.Combine (Application.streamingAssetsPath, filepath);
  889. if (progressChanged != null)
  890. progressChanged (filepath, 0);
  891. yield return null;
  892. if (progressChanged != null)
  893. progressChanged (filepath, 1);
  894. if (File.Exists (destPath)) {
  895. if (completed != null)
  896. completed (destPath);
  897. } else {
  898. if (errorOccurred != null) {
  899. errorOccurred (filepath, "Unknown Error", 0);
  900. } else {
  901. if (completed != null)
  902. completed (String.Empty);
  903. }
  904. }
  905. #endif
  906. yield break;
  907. }
  908. /**
  909. * Gets the multiple readable paths of files in the "StreamingAssets" folder by using coroutines.
  910. * <p>
  911. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  912. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  913. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  914. *
  915. * @param filepaths an array of relative file paths starting from the "StreamingAssets" folder.
  916. * @param allCompleted a callback function that is called when the process is completed. Returns an array of readable file paths.
  917. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  918. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  919. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  920. */
  921. public static IEnumerator getMultipleFilePathsAsync (string[] filepaths, Action<string[]> allCompleted, bool refresh = false, int timeout = 0)
  922. {
  923. return getMultipleFilePathsAsync (filepaths, allCompleted, null, null, refresh, timeout);
  924. }
  925. /**
  926. * Gets the multiple readable paths of files in the "StreamingAssets" folder by using coroutines.
  927. * <p>
  928. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  929. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  930. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  931. *
  932. * @param filepaths an array of relative file paths starting from the "StreamingAssets" folder.
  933. * @param allCompleted a callback function that is called when the process is completed. Returns an array of readable file paths.
  934. * @param progressChanged a callback function that is called when the process is the progress. Returns the file path and a progress value (0.0 to 1.0).
  935. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  936. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  937. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  938. */
  939. public static IEnumerator getMultipleFilePathsAsync (string[] filepaths, Action<string[]> allCompleted, Action<string, float> progressChanged, bool refresh = false, int timeout = 0)
  940. {
  941. return getMultipleFilePathsAsync (filepaths, allCompleted, progressChanged, null, refresh, timeout);
  942. }
  943. /**
  944. * Gets the multiple readable paths of files in the "StreamingAssets" folder by using coroutines.
  945. * <p>
  946. * <br>Set a relative file path from the starting point of the "StreamingAssets" folder. e.g. "foobar.txt" or "hogehoge/foobar.txt".
  947. * <br>[Android] The target file that exists in the "StreamingAssets" folder is copied into the folder of the Application.persistentDataPath. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  948. * <br>[WebGL] The target file in the "StreamingAssets" folder is copied to the WebGL's virtual filesystem. If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  949. *
  950. * @param filepaths an array of relative file paths starting from the "StreamingAssets" folder.
  951. * @param allCompleted a callback function that is called when the process is completed. Returns an array of readable file paths.
  952. * @param progressChanged a callback function that is called when the process is the progress. Returns the file path and a progress value (0.0 to 1.0).
  953. * @param errorOccurred a callback function that is called when the process is error occurred. Returns the file path and an error string and an error response code.
  954. * @param refresh [Android][WebGL] If refresh flag is false, when the file has already been copied, the file is not copied. If refresh flag is true, the file is always copied.
  955. * @param timeout [Android 2017.1+][WebGL] Sets UnityWebRequest to attempt to abort after the number of seconds in timeout has passed. No timeout is applied when timeout is set to 0 and this property defaults to 0.
  956. * @return returns an IEnumerator object. Yielding the IEnumerator inside a coroutine will cause the coroutine to pause until the UnityWebRequest encounters a system error or finishes communicating.
  957. */
  958. public static IEnumerator getMultipleFilePathsAsync (string[] filepaths, Action<string[]> allCompleted, Action<string, float> progressChanged, Action<string, string, long> errorOccurred, bool refresh = false, int timeout = 0)
  959. {
  960. string[] readableFilePaths = new string[filepaths.Length];
  961. for (int i = 0; i < filepaths.Length; i++) {
  962. yield return getFilePathAsync (filepaths [i], (result) => {
  963. readableFilePaths [i] = result;
  964. }, progressChanged, errorOccurred, refresh, timeout);
  965. }
  966. if (allCompleted != null)
  967. allCompleted (readableFilePaths);
  968. }
  969. private static char[] chTrims = {
  970. '.',
  971. #if UNITY_WINRT_8_1 && !UNITY_EDITOR
  972. '/',
  973. '\\'
  974. #else
  975. System.IO.Path.DirectorySeparatorChar,
  976. System.IO.Path.AltDirectorySeparatorChar
  977. #endif
  978. };
  979. /// <summary>
  980. /// if true, CvException is thrown instead of calling Debug.LogError (msg).
  981. /// </summary>
  982. #pragma warning disable 0414
  983. private static bool throwOpenCVException = false;
  984. #pragma warning restore 0414
  985. /**
  986. * Sets the debug mode.
  987. * <p>
  988. * <br>if debugMode is true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.However, if throwException is true, CvException is thrown instead of calling Debug.LogError (msg).
  989. * <br>Please use as follows.
  990. * <br>Utils.setDebugMode(true);
  991. * <br>aaa
  992. * <br>bbb
  993. * <br>ccc
  994. * <br>Utils.setDebugMode(false);
  995. *
  996. * @param debugMode if true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.
  997. * @param throwException if true, CvException is thrown instead of calling Debug.LogError (msg).
  998. */
  999. public static void setDebugMode (bool debugMode, bool throwException = false)
  1000. {
  1001. #if (UNITY_PRO_LICENSE || UNITY_5 || UNITY_5_3_OR_NEWER)
  1002. OpenCVForUnity_SetDebugMode (debugMode);
  1003. if (debugMode) {
  1004. OpenCVForUnity_SetDebugLogFunc (debugLogFunc);
  1005. // OpenCVForUnity_DebugLogTest ();
  1006. } else {
  1007. OpenCVForUnity_SetDebugLogFunc (null);
  1008. }
  1009. throwOpenCVException = throwException;
  1010. #endif
  1011. }
  1012. #if (UNITY_PRO_LICENSE || UNITY_5 || UNITY_5_3_OR_NEWER)
  1013. private delegate void DebugLogDelegate (string str);
  1014. [MonoPInvokeCallback (typeof(DebugLogDelegate))]
  1015. private static void debugLogFunc (string str)
  1016. {
  1017. if (throwOpenCVException) {
  1018. throw new CvException (str);
  1019. } else {
  1020. Debug.LogError (str);
  1021. }
  1022. }
  1023. #endif
  1024. internal static int URShift (int number, int bits)
  1025. {
  1026. if (number >= 0)
  1027. return number >> bits;
  1028. else
  1029. return (number >> bits) + (2 << ~bits);
  1030. }
  1031. internal static long URShift (long number, int bits)//TODO:@check
  1032. {
  1033. if (number >= 0)
  1034. return number >> bits;
  1035. else
  1036. return (number >> bits) + (2 << ~bits);
  1037. }
  1038. internal static int HashContents<T> (this IEnumerable<T> enumerable)//TODO:@check
  1039. {
  1040. int hash = 0x218A9B2C;
  1041. foreach (var item in enumerable) {
  1042. int thisHash = item.GetHashCode ();
  1043. //mix up the bits.
  1044. hash = thisHash ^ ((hash << 5) + hash);
  1045. }
  1046. return hash;
  1047. }
  1048. #if (UNITY_IOS || UNITY_WEBGL) && !UNITY_EDITOR
  1049. const string LIBNAME = "__Internal";
  1050. #else
  1051. const string LIBNAME = "opencvforunity";
  1052. #endif
  1053. [DllImport (LIBNAME)]
  1054. private static extern void OpenCVForUnity_SetDebugMode (bool flag);
  1055. [DllImport (LIBNAME)]
  1056. private static extern void OpenCVForUnity_SetDebugLogFunc (DebugLogDelegate func);
  1057. [DllImport (LIBNAME)]
  1058. private static extern void OpenCVForUnity_DebugLogTest ();
  1059. [DllImport (LIBNAME)]
  1060. private static extern void OpenCVForUnity_MatToTexture (IntPtr mat, IntPtr textureColors, bool flip, int flipCode, bool flipAfter);
  1061. [DllImport (LIBNAME)]
  1062. private static extern void OpenCVForUnity_TextureToMat (IntPtr textureColors, IntPtr Mat, bool flip, int flipCode);
  1063. [DllImport (LIBNAME)]
  1064. private static extern void OpenCVForUnity_MatDataToByteArray (IntPtr mat, IntPtr byteArray);
  1065. [DllImport (LIBNAME)]
  1066. private static extern void OpenCVForUnity_ByteArrayToMatData (IntPtr byteArray, IntPtr Mat);
  1067. [DllImport (LIBNAME)]
  1068. private static extern void OpenCVForUnity_SetTextureFromUnity (System.IntPtr texture, int width, int height, int bytesPerPixel);
  1069. [DllImport (LIBNAME)]
  1070. private static extern void OpenCVForUnity_SetByteArrayFromUnity (System.IntPtr byteArray, int width, int height, int bytesPerPixel);
  1071. [DllImport (LIBNAME)]
  1072. private static extern IntPtr OpenCVForUnity_GetRenderEventFunc ();
  1073. #if UNITY_WEBGL && !UNITY_EDITOR
  1074. private static bool isWebGLPluginRegistered = false;
  1075. [DllImport(LIBNAME)]
  1076. private static extern void OpenCVForUnity_RegisterPlugin();
  1077. #endif
  1078. }
  1079. }