XDKTools.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Runtime.InteropServices;
  4. using UnityEngine;
  5. using OpenCVForUnity;
  6. using OpenCVForUnity.CoreModule;
  7. using OpenCVForUnity.ImgcodecsModule;
  8. using OpenCVForUnity.ImgprocModule;
  9. using OpenCVForUnity.UnityUtils;
  10. using OpenCVForUnity.Calib3dModule;
  11. using System.Text;
  12. using System.IO;
  13. using System.Net;
  14. namespace Seengene.XDKUnityPluginCloud {
  15. public class XDKTools {
  16. #region File tools
  17. /// <summary>
  18. /// 格式化路径成Asset的标准格式
  19. /// </summary>
  20. /// <param name="filePath"></param>
  21. /// <returns></returns>
  22. public static string FormatAssetPath(string filePath) {
  23. var newFilePath1 = filePath.Replace("\\", "/");
  24. var newFilePath2 = newFilePath1.Replace("//", "/").Trim();
  25. newFilePath2 = newFilePath2.Replace("///", "/").Trim();
  26. newFilePath2 = newFilePath2.Replace("\\\\", "/").Trim();
  27. return newFilePath2;
  28. }
  29. public static string GetRelativePathFromFullPath(string fullPath) {
  30. string mp = fullPath;
  31. mp = mp.Substring(mp.IndexOf("Assets"));
  32. mp = mp.Replace('\\', '/');
  33. return mp;
  34. }
  35. /// <summary>
  36. /// 获取下载文件的大小
  37. /// </summary>
  38. /// <returns>The length.</returns>
  39. /// <param name="url">URL.</param>
  40. public static long GetFileLengthByUrl(string url) {
  41. HttpWebRequest requet = HttpWebRequest.Create(url) as HttpWebRequest;
  42. requet.Method = "HEAD";
  43. HttpWebResponse response = requet.GetResponse() as HttpWebResponse;
  44. return response.ContentLength;
  45. }
  46. /// <summary>
  47. /// 计算文件大小函数(保留两位小数),Size为字节大小
  48. /// </summary>
  49. /// <param name="size">初始文件大小</param>
  50. /// <returns></returns>
  51. public static string GetFormatFileSize(long size) {
  52. var num = 1024.00; //byte
  53. if (size < num)
  54. return size + "B";
  55. if (size < Math.Pow(num, 2))
  56. return (size / num).ToString("f2") + "K"; //kb
  57. if (size < Math.Pow(num, 3))
  58. return (size / Math.Pow(num, 2)).ToString("f2") + "M"; //M
  59. if (size < Math.Pow(num, 4))
  60. return (size / Math.Pow(num, 3)).ToString("f2") + "G"; //G
  61. return (size / Math.Pow(num, 4)).ToString("f2") + "T"; //T
  62. }
  63. #endregion of File tools
  64. #region Texture Format Compress
  65. public static byte[] GetGrayTextureBytes(byte[] imageBuffer, TextureFormat textureFormat, int imageHeight, int imageWidth) {
  66. if (textureFormat == TextureFormat.R8) {
  67. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  68. grayMat.put(0, 0, imageBuffer);
  69. try {
  70. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 100);
  71. MatOfByte jpgMat = new MatOfByte();
  72. if (Imgcodecs.imencode(".jpeg", grayMat, jpgMat, compressionParams)) {
  73. return jpgMat.toArray();
  74. } else {
  75. return null;
  76. }
  77. } catch (Exception e) {
  78. Debug.LogErrorFormat("图片转灰度图、压缩JPG格式失败: ", e.Message);
  79. return null;
  80. }
  81. } else if (textureFormat == TextureFormat.RGB24) {
  82. Mat imgMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC3);
  83. imgMat.put(0, 0, imageBuffer);
  84. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  85. Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
  86. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 90);
  87. MatOfByte jpgMat = new MatOfByte();
  88. if (Imgcodecs.imencode(".jpeg", grayMat, jpgMat, compressionParams)) {
  89. return jpgMat.toArray();
  90. } else {
  91. return null;
  92. }
  93. } else if (textureFormat == TextureFormat.ARGB32) {
  94. Mat imgMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC4);
  95. imgMat.put(0, 0, imageBuffer);
  96. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  97. Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
  98. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 90);
  99. MatOfByte jpgMat = new MatOfByte();
  100. if (Imgcodecs.imencode(".jpeg", grayMat, jpgMat, compressionParams)) {
  101. return jpgMat.toArray();
  102. } else {
  103. return null;
  104. }
  105. } else {
  106. Debug.LogErrorFormat("XDKTools.GetGrayTextureBytesAndroid,图片压缩失败,不支持的图片格式:{0}", textureFormat);
  107. return null;
  108. }
  109. }
  110. public static byte[] GetGrayUndistortTextureBytes(byte[] imageBuffer, TextureFormat textureFormat, int imageHeight, int imageWidth, float[] cameraIntrinsic, float[] disCoeffsArray) {
  111. if (textureFormat == TextureFormat.R8) {
  112. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  113. grayMat.put(0, 0, imageBuffer);
  114. try {
  115. Mat undistortMat = Mat.zeros(imageHeight, imageWidth, CvType.CV_8UC1);
  116. Mat cameraMatrix = new Mat(3, 3, CvType.CV_32FC1);
  117. cameraMatrix.put(0, 0, cameraIntrinsic);
  118. //Debug.LogFormat("cameraMatrix: {0}", cameraMatrix.dump());
  119. Mat discoeffs = new Mat(1, 8, CvType.CV_32FC1);
  120. discoeffs.put(0, 0, disCoeffsArray);
  121. //Debug.LogFormat("discoeffs: {0}", discoeffs.dump());
  122. Calib3d.undistort(grayMat, undistortMat, cameraMatrix, discoeffs);
  123. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 100);
  124. MatOfByte jpgMat = new MatOfByte();
  125. if (Imgcodecs.imencode(".jpeg", undistortMat, jpgMat, compressionParams)) {
  126. return jpgMat.toArray();
  127. } else {
  128. return null;
  129. }
  130. } catch (Exception e) {
  131. Debug.LogErrorFormat("图片转灰度图、去畸变、压缩JPG格式失败: ", e.Message);
  132. return null;
  133. }
  134. } else if (textureFormat == TextureFormat.RGB24) {
  135. Mat imgMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC3);
  136. imgMat.put(0, 0, imageBuffer);
  137. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  138. Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
  139. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 90);
  140. MatOfByte jpgMat = new MatOfByte();
  141. if (Imgcodecs.imencode(".jpeg", grayMat, jpgMat, compressionParams)) {
  142. return jpgMat.toArray();
  143. } else {
  144. return null;
  145. }
  146. } else if (textureFormat == TextureFormat.ARGB32) {
  147. Mat imgMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC4);
  148. imgMat.put(0, 0, imageBuffer);
  149. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  150. Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
  151. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 90);
  152. MatOfByte jpgMat = new MatOfByte();
  153. if (Imgcodecs.imencode(".jpeg", grayMat, jpgMat, compressionParams)) {
  154. return jpgMat.toArray();
  155. } else {
  156. return null;
  157. }
  158. } else {
  159. Debug.LogErrorFormat("XDKTools.GetGrayTextureBytesAndroid,图片压缩失败,不支持的图片格式:{0}", textureFormat);
  160. return null;
  161. }
  162. }
  163. public static byte[] GetGrayUndistortTextureBytes(byte[] imageBuffer, TextureFormat textureFormat, int imageHeight, int imageWidth, CameraCalibration cameraCalibration) {
  164. if (textureFormat == TextureFormat.R8) {
  165. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  166. grayMat.put(0, 0, imageBuffer);
  167. try {
  168. Mat undistortMat = Mat.zeros(imageHeight, imageWidth, CvType.CV_8UC1);
  169. Mat cameraMatrix = new Mat(3, 3, CvType.CV_32FC1);
  170. // 计算相机内参
  171. float intrinsics_00 = cameraCalibration.focal_length.x;
  172. float intrinsics_01 = 0;
  173. float intrinsics_02 = cameraCalibration.principal_point.x;
  174. float intrinsics_10 = 0;
  175. float intrinsics_11 = cameraCalibration.focal_length.y;
  176. float intrinsics_12 = cameraCalibration.principal_point.y;
  177. float intrinsics_20 = 0;
  178. float intrinsics_21 = 0;
  179. float intrinsics_22 = 1;
  180. float[] cameraIntrinsicData = new float[9] { intrinsics_00, intrinsics_01, intrinsics_02 ,
  181. intrinsics_10, intrinsics_11, intrinsics_12 ,
  182. intrinsics_20, intrinsics_21, intrinsics_22 };
  183. cameraMatrix.put(0, 0, cameraIntrinsicData);
  184. Debug.LogFormat("cameraMatrix: {0}", cameraMatrix.dump());
  185. // 畸变参数
  186. Mat discoeffs = new Mat(1, 8, CvType.CV_32FC1);
  187. float discoeffs_0 = cameraCalibration.radial_distortion_8[0];
  188. float discoeffs_1 = cameraCalibration.radial_distortion_8[1];
  189. float discoeffs_2 = cameraCalibration.radial_distortion_8[2];
  190. float discoeffs_3 = cameraCalibration.radial_distortion_8[3];
  191. float discoeffs_4 = cameraCalibration.radial_distortion_8[4];
  192. float discoeffs_5 = cameraCalibration.radial_distortion_8[5];
  193. float discoeffs_6 = cameraCalibration.radial_distortion_8[6];
  194. float discoeffs_7 = cameraCalibration.radial_distortion_8[7];
  195. float[] disCoeffsData = new float[8] { discoeffs_0, discoeffs_1, discoeffs_2, discoeffs_3, discoeffs_4, discoeffs_5, discoeffs_6, discoeffs_7 };
  196. discoeffs.put(0, 0, disCoeffsData);
  197. Debug.LogFormat("discoeffs: {0}", discoeffs.dump());
  198. if (cameraCalibration.fish_eye == false) {
  199. Calib3d.undistort(grayMat, undistortMat, cameraMatrix, discoeffs);
  200. } else {
  201. Calib3d.fisheye_undistortImage(grayMat, undistortMat, cameraMatrix, discoeffs);
  202. }
  203. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 100);
  204. MatOfByte jpgMat = new MatOfByte();
  205. if (Imgcodecs.imencode(".jpeg", undistortMat, jpgMat, compressionParams)) {
  206. return jpgMat.toArray();
  207. } else {
  208. return null;
  209. }
  210. } catch (Exception e) {
  211. Debug.LogErrorFormat("图片转灰度图、去畸变、压缩JPG格式失败: ", e.Message);
  212. return null;
  213. }
  214. } else if (textureFormat == TextureFormat.RGB24) {
  215. Mat imgMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC3);
  216. imgMat.put(0, 0, imageBuffer);
  217. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  218. Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
  219. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 90);
  220. MatOfByte jpgMat = new MatOfByte();
  221. if (Imgcodecs.imencode(".jpeg", grayMat, jpgMat, compressionParams)) {
  222. return jpgMat.toArray();
  223. } else {
  224. return null;
  225. }
  226. } else if (textureFormat == TextureFormat.ARGB32) {
  227. Mat imgMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC4);
  228. imgMat.put(0, 0, imageBuffer);
  229. Mat grayMat = new Mat(imageHeight, imageWidth, CvType.CV_8UC1);
  230. Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
  231. MatOfInt compressionParams = new MatOfInt(Imgcodecs.IMWRITE_JPEG_QUALITY, 90);
  232. MatOfByte jpgMat = new MatOfByte();
  233. if (Imgcodecs.imencode(".jpeg", grayMat, jpgMat, compressionParams)) {
  234. return jpgMat.toArray();
  235. } else {
  236. return null;
  237. }
  238. } else {
  239. Debug.LogErrorFormat("XDKTools.GetGrayTextureBytesAndroid,图片压缩失败,不支持的图片格式:{0}", textureFormat);
  240. return null;
  241. }
  242. }
  243. public static MatOfByte GetGrayTextureMat(Texture2D texture2D) {
  244. Mat imgMat = new Mat(texture2D.height, texture2D.width, CvType.CV_8UC4);
  245. Utils.texture2DToMat(texture2D, imgMat);
  246. Mat grayMat = new Mat(texture2D.height, texture2D.width, CvType.CV_8UC1);
  247. Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_RGBA2GRAY);
  248. MatOfByte grayMatOfByte = new MatOfByte(grayMat);
  249. return grayMatOfByte;
  250. }
  251. public static Texture2D VerticalFlipTexture(Texture2D texture) {
  252. //得到图片的宽高
  253. int width = texture.width;
  254. int height = texture.height;
  255. Texture2D flipTexture = new Texture2D(width, height);
  256. for (int i = 0; i < height; i++) {
  257. flipTexture.SetPixels(0, i, width, 1, texture.GetPixels(0, height - i - 1, width, 1));
  258. }
  259. flipTexture.Apply();
  260. return flipTexture;
  261. }
  262. //byte[]转换为Intptr
  263. public static IntPtr BytesToIntptr(byte[] bytes) {
  264. return System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(bytes, 0);
  265. }
  266. public static IntPtr ArrayToIntptr(Array array) {
  267. return System.Runtime.InteropServices.Marshal.UnsafeAddrOfPinnedArrayElement(array, 0);
  268. }
  269. public static byte[] IntPtrToBytes(IntPtr imagePtr, int imageSize) {
  270. byte[] imageBytes = new byte[imageSize];
  271. Marshal.Copy(imagePtr, imageBytes, 0, imageSize);
  272. return imageBytes;
  273. }
  274. public static IntPtr FloatArrayToIntPtr(float[] floatArray) {
  275. int size = sizeof(float) * floatArray.Length;
  276. IntPtr ptr = Marshal.AllocHGlobal(size);
  277. Marshal.Copy(floatArray, 0, ptr, floatArray.Length);
  278. return ptr;
  279. }
  280. public static float[] IntPtrToFloatArray(IntPtr ptr, int count) {
  281. float[] image2DPoints = new float[count];
  282. Marshal.Copy(ptr, image2DPoints, 0, count);
  283. return image2DPoints;
  284. }
  285. public static Texture2D LoadLocalImage(string path) {
  286. FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
  287. fileStream.Seek(0, SeekOrigin.Begin);
  288. byte[] imgBytes = new byte[fileStream.Length];
  289. fileStream.Read(imgBytes, 0, (int)fileStream.Length);
  290. fileStream.Close();
  291. fileStream.Dispose();
  292. fileStream = null;
  293. Texture2D texture = new Texture2D(1280, 720);
  294. texture.LoadImage(imgBytes);
  295. return texture;
  296. }
  297. public static byte[] GetFileStream(string path) {
  298. FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
  299. fileStream.Seek(0, SeekOrigin.Begin);
  300. byte[] imgBytes = new byte[fileStream.Length];
  301. fileStream.Read(imgBytes, 0, (int)fileStream.Length);
  302. fileStream.Close();
  303. fileStream.Dispose();
  304. fileStream = null;
  305. return imgBytes;
  306. }
  307. #endregion of Texture Format Compress
  308. #region Debug String Format
  309. public static string ListVectro2ToString(List<Vector2> listV2, string format = "f2") {
  310. StringBuilder sb = new StringBuilder();
  311. for (int i = 0; i < listV2.Count; i++) {
  312. sb.Append(listV2[i].ToString(format));
  313. sb.Append(",");
  314. }
  315. return sb.ToString();
  316. }
  317. public static string ListVector3ToString(List<Vector3> listV3, string format = "f2") {
  318. StringBuilder sb = new StringBuilder();
  319. for (int i = 0; i < listV3.Count; i++) {
  320. sb.Append(listV3[i].ToString(format));
  321. sb.Append(",");
  322. }
  323. return sb.ToString();
  324. }
  325. public static string ListDoubleToString(List<double> listDouble, string format = "f2") {
  326. StringBuilder sb = new StringBuilder();
  327. for (int i = 0; i < listDouble.Count; i++) {
  328. sb.Append(listDouble[i].ToString(format));
  329. sb.Append(",");
  330. }
  331. return sb.ToString();
  332. }
  333. public static string ListFloatToString(List<float> listFloat, string format = "f2") {
  334. StringBuilder sb = new StringBuilder();
  335. for (int i = 0; i < listFloat.Count; i++) {
  336. sb.Append(listFloat[i].ToString(format));
  337. sb.Append(",");
  338. }
  339. return sb.ToString();
  340. }
  341. /// <summary>
  342. /// Float数组 格式化输出
  343. /// </summary>
  344. /// <param name="arrayFloat"></param>
  345. /// <param name="format">格式化,小数点保留几位</param>
  346. /// <returns></returns>
  347. public static string ArrayFloatToString(float[] arrayFloat, string format = "f2") {
  348. if (arrayFloat == null) return null;
  349. StringBuilder sb = new StringBuilder();
  350. for (int i = 0; i < arrayFloat.Length; i++) {
  351. sb.Append(arrayFloat[i].ToString(format));
  352. sb.Append(",");
  353. }
  354. return sb.ToString();
  355. }
  356. public static string OneDimensionArrayToString(string[] arr) {
  357. StringBuilder sb = new StringBuilder();
  358. for (int i = 0; i < arr.Length - 1; i++) {
  359. sb.Append(arr[i]);
  360. sb.Append(",");
  361. }
  362. sb.Append(arr[arr.Length - 1]);
  363. return sb.ToString();
  364. }
  365. public static string TwoDimensionArrayToString(float[,] arr) {
  366. StringBuilder sb = new StringBuilder();
  367. int coutRow = arr.GetLength(0);
  368. int countColumn = arr.GetLength(1);
  369. for (int i = 0; i < coutRow; i++) {
  370. for (int j = 0; j < countColumn; j++) {
  371. sb.Append(arr[i, j]);
  372. sb.Append(",");
  373. }
  374. }
  375. return sb.ToString();
  376. }
  377. //自定义输出字符数组方法
  378. public static string GetBytesString(byte[] bytes) {
  379. return GetBytesString(bytes, 0, bytes.Length, ",");
  380. }
  381. public static string GetBytesString(byte[] bytes, int index, int count, string sep) {
  382. if (count > bytes.Length) count = bytes.Length;
  383. var sb = new StringBuilder();
  384. for (int i = index; i < count - 1; i++) {
  385. sb.Append(bytes[i].ToString("X2") + sep);
  386. }
  387. sb.Append(bytes[index + count - 1].ToString("X2"));
  388. return sb.ToString();
  389. }
  390. }
  391. #endregion of Debug String Format
  392. }