CameraCalibrationLoader.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Xml;
  5. using UnityEngine;
  6. using Seengene.XDKUnityPluginCloud;
  7. public class CameraCalibrationLoader {
  8. /// <summary>
  9. /// 眼类型
  10. /// </summary>
  11. public enum EyeType {
  12. /// <summary>
  13. /// 左眼
  14. /// </summary>
  15. LeftEye = 0,
  16. /// <summary>
  17. /// 右眼
  18. /// </summary>
  19. RightEye = 1
  20. }
  21. private static string configXmlPath;
  22. private const string k_DefaultConfigXmlPath = "/persist/qvr/device_calibration.xml";
  23. public const string k_XmlDocumentName = "device_calibration.xml";
  24. public const string k_XmlNodeName_Root = "DeviceConfiguration";
  25. public const string k_XmlNodeName_LevelOne = "Camera";
  26. public const string k_XmlNodeName_LevelTwo = "Calibration";
  27. public const string k_XmlNodeAttributeName_EyeID = "id";
  28. public const string k_XmlNodeAttributeName_FocalLength = "focal_length";
  29. public const string k_XmlNodeAttributeName_PrincipalPoint = "principal_point";
  30. public const string k_XmlNodeAttributeName_Resolution = "size";
  31. public const string k_XmlNodeAttributeName_FishEye = "fish_eye";
  32. public const string k_XmlNodeAttributeName_RadialDistortion8 = "radial_distortion_8";
  33. public const string k_XmlNodeAttributeName_Model = "model";
  34. public const string k_XmlNodeAttributeName_RadialDistortion = "radial_distortion";
  35. private static void Init() {
  36. #if UNITY_EDITOR
  37. configXmlPath = Path.Combine(Application.streamingAssetsPath, k_XmlDocumentName);
  38. #else
  39. configXmlPath = k_DefaultConfigXmlPath;
  40. #endif
  41. }
  42. public static CameraCalibration GetCameraCalibration(EyeType eyeType) {
  43. Init();
  44. if (!File.Exists(configXmlPath)) {
  45. Debug.LogErrorFormat("读取相机内参失败,相机标定文件不存在: {0}", configXmlPath);
  46. return null;
  47. }
  48. Vector2 focalLength = Vector2.zero;
  49. Vector2 principalPoint = Vector3.zero;
  50. Vector2Int resolution = Vector2Int.zero;
  51. bool fishEye = false;
  52. float[] radialDistortion8 = null;
  53. string model = string.Empty;
  54. float[] radialDistortion = null;
  55. XmlDocument myXmlDoc = new XmlDocument();
  56. string str = File.ReadAllText(configXmlPath);
  57. myXmlDoc.LoadXml(str);
  58. XmlNode rootNode = myXmlDoc.SelectSingleNode(k_XmlNodeName_Root);
  59. XmlNodeList nodeList_L1 = rootNode.ChildNodes;
  60. foreach (XmlNode node_L1 in nodeList_L1) {
  61. if (node_L1.Name == k_XmlNodeName_LevelOne) {
  62. // 标识位,是否是要查找的相机内参的眼睛
  63. bool isTargetEye = false;
  64. XmlAttributeCollection attributeCol_L1 = node_L1.Attributes;
  65. foreach (XmlAttribute attri in attributeCol_L1) {
  66. string name = attri.Name;
  67. string value = attri.Value;
  68. if (name == k_XmlNodeAttributeName_EyeID && value == ((int)eyeType).ToString()) {
  69. isTargetEye = true;
  70. break;
  71. }
  72. }
  73. if (isTargetEye) {
  74. if (node_L1.HasChildNodes) {
  75. XmlNodeList nodeList_L2 = node_L1.ChildNodes;
  76. foreach (XmlNode node_L2 in nodeList_L2) {
  77. string name = node_L2.Name;
  78. if (name == k_XmlNodeName_LevelTwo) {
  79. XmlAttributeCollection attibuteCol_L2 = node_L2.Attributes;
  80. foreach (XmlAttribute attri in attibuteCol_L2) {
  81. if (attri.Name == k_XmlNodeAttributeName_Resolution) {
  82. // 图片分辨率
  83. try {
  84. string value = attri.Value;
  85. string[] arrValue = value.Split(" "[0]);
  86. if (arrValue.Length >= 2) {
  87. int width = int.Parse(arrValue[0]);
  88. int height = int.Parse(arrValue[1]);
  89. resolution = new Vector2Int(width, height);
  90. } else {
  91. Debug.LogErrorFormat("读取相机内参失败:{0}", "解析图片分辨率时出错");
  92. break;
  93. }
  94. } catch (Exception e) {
  95. Debug.LogErrorFormat("读取相机内参失败:{0}", e.Message);
  96. break;
  97. }
  98. }
  99. if (attri.Name == k_XmlNodeAttributeName_PrincipalPoint) {
  100. // 主点
  101. try {
  102. string value = attri.Value;
  103. string[] arrValue = value.Split(" "[0]);
  104. if (arrValue.Length >= 2) {
  105. float x = float.Parse(arrValue[0]);
  106. float y = float.Parse(arrValue[1]);
  107. principalPoint = new Vector2(x, y);
  108. } else {
  109. Debug.LogErrorFormat("读取相机内参失败:{0}", "解析图片主点参数时出错");
  110. break;
  111. }
  112. } catch (Exception e) {
  113. Debug.LogErrorFormat("读取相机内参失败:{0}", e.Message);
  114. break;
  115. }
  116. }
  117. if (attri.Name == k_XmlNodeAttributeName_FocalLength) {
  118. // 焦距
  119. try {
  120. string value = attri.Value;
  121. string[] arrValue = value.Split(" "[0]);
  122. if (arrValue.Length >= 2) {
  123. float x = float.Parse(arrValue[0]);
  124. float y = float.Parse(arrValue[1]);
  125. focalLength = new Vector2(x, y);
  126. } else {
  127. Debug.LogErrorFormat("读取相机内参失败:{0}", "解析图片焦距参数时出错");
  128. break;
  129. }
  130. } catch (Exception e) {
  131. Debug.LogErrorFormat("读取相机内参失败:{0}", e.Message);
  132. break;
  133. }
  134. }
  135. if (attri.Name == k_XmlNodeAttributeName_FishEye) {
  136. // 是否是鱼眼图
  137. try {
  138. string value = attri.Value;
  139. if (value == "true") {
  140. fishEye = true;
  141. } else {
  142. fishEye = false;
  143. }
  144. } catch (Exception e) {
  145. Debug.LogErrorFormat("读取相机内参失败:{0}", e.Message);
  146. break;
  147. }
  148. }
  149. if (attri.Name == k_XmlNodeAttributeName_RadialDistortion8) {
  150. // 8位图片畸变参数
  151. try {
  152. string value = attri.Value;
  153. //Debug.Log("radialDistortion8: " + value);
  154. string[] arrValue = value.Split(" "[0]);
  155. //Debug.Log("arrValue.Length: " + arrValue.Length);
  156. //Debug.Log(XDKTools.OneDimensionArrayToString(arrValue));
  157. if (arrValue.Length >= 8) {
  158. float p0 = float.Parse(arrValue[0]);
  159. float p1 = float.Parse(arrValue[1]);
  160. float p2 = float.Parse(arrValue[2]);
  161. float p3 = float.Parse(arrValue[3]);
  162. float p4 = float.Parse(arrValue[4]);
  163. float p5 = float.Parse(arrValue[5]);
  164. float p6 = float.Parse(arrValue[6]);
  165. float p7 = float.Parse(arrValue[7]);
  166. radialDistortion8 = new float[8] { p0, p1, p2, p3, p4, p5, p6, p7 };
  167. //Debug.Log("radialDistortion8: " + XDKTools.ArrayFloatToString(radialDistortion8));
  168. } else {
  169. Debug.LogErrorFormat("读取相机内参失败:{0}", "解析图片\"8位图片畸变参数\"时出错");
  170. break;
  171. }
  172. } catch (Exception e) {
  173. Debug.LogErrorFormat("读取相机内参失败:{0}", e.Message);
  174. break;
  175. }
  176. }
  177. if (attri.Name == k_XmlNodeAttributeName_Model) {
  178. // 相机模型 model
  179. try {
  180. model = attri.Value;
  181. //Debug.Log("model: " + model);
  182. } catch (Exception e) {
  183. Debug.LogErrorFormat("读取相机内参失败:{0}", e.Message);
  184. break;
  185. }
  186. }
  187. if (attri.Name == k_XmlNodeAttributeName_RadialDistortion) {
  188. // 图片畸变参数
  189. try {
  190. string value = attri.Value;
  191. //Debug.Log("radialDistortion: " + value);
  192. string[] arrValue = value.Split(" "[0]);
  193. //Debug.Log("arrValue.Length: " + arrValue.Length);
  194. //Debug.Log(XDKTools.OneDimensionArrayToString(arrValue));
  195. if (arrValue.Length >= 6) {
  196. float p0 = float.Parse(arrValue[0]);
  197. float p1 = float.Parse(arrValue[1]);
  198. float p2 = float.Parse(arrValue[2]);
  199. float p3 = float.Parse(arrValue[3]);
  200. float p4 = float.Parse(arrValue[4]);
  201. float p5 = float.Parse(arrValue[5]);
  202. radialDistortion = new float[6] { p0, p1, p2, p3, p4, p5 };
  203. } else {
  204. Debug.LogErrorFormat("读取相机内参失败:{0}", "解析图片\"图片畸变参数\"时出错");
  205. }
  206. Debug.Log("radialDistortion: " + radialDistortion);
  207. } catch (Exception e) {
  208. Debug.LogErrorFormat("读取相机内参失败:{0}", e.Message);
  209. break;
  210. }
  211. }
  212. }
  213. }
  214. }
  215. }
  216. }
  217. }
  218. }
  219. if (focalLength != Vector2.zero && principalPoint != Vector2.zero && resolution != Vector2.zero) {
  220. CameraCalibration cameraIntrinsics = new CameraCalibration(focalLength, principalPoint, resolution, fishEye, radialDistortion8, model, radialDistortion);
  221. return cameraIntrinsics;
  222. } else {
  223. return null;
  224. }
  225. }
  226. }