RoughPositioningAnalyser.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. using AI.Common;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Windows.Media;
  9. namespace HumanOrganSegDemo.RoughPositioningAnalyser
  10. {
  11. public class RoughPositioningAnalyser :IRoughPositioningAnalyser
  12. {
  13. #region private
  14. private int countSum = 0;
  15. private List<int> countXList = new List<int>();
  16. private List<int> countYList = new List<int>();
  17. private List<int> countMidXList = new List<int>();
  18. private List<int> countMidYList = new List<int>();
  19. private List<int> countList = new List<int>();
  20. #endregion
  21. #region 实现
  22. /// <summary>
  23. /// 获取图像坐标系下初始扫查路径点
  24. /// </summary>
  25. /// <param name="organ"></param>
  26. /// <param name="HumanOrientationInPCS"></param>
  27. /// <param name="OrganContours"></param>
  28. /// <returns></returns>
  29. public Point2D[] GetRoughSanPathInPCS(EnumOrgans organ, Point2D humanOrientationInPCS, Rect humanRoi, ContourPoints organContours)
  30. {
  31. Point2D[] result;
  32. switch (organ)
  33. {
  34. case EnumOrgans.Liver:
  35. result = GetLiverRoughSanPathInPCS(humanOrientationInPCS, humanRoi, organContours);
  36. break;
  37. case EnumOrgans.Heart:
  38. result = GetHeartRoughSanPathInPCS(humanOrientationInPCS, humanRoi, organContours);
  39. break;
  40. default:
  41. throw new Exception("Invalid organ name!");
  42. }
  43. return result;
  44. }
  45. #endregion
  46. #region private funcs
  47. private Point2D[] GetLiverRoughSanPathInPCS(Point2D humanOrientationInPCS, Rect humanRoi, ContourPoints organContours)
  48. {
  49. int tempX = 0;
  50. int tempY = 0;
  51. Point2D[] contours = (Point2D[])organContours.Points.Clone();
  52. for (int j = 0; j < contours.Length - 1; j++)
  53. {
  54. if (contours[j + 1].X < contours[j].X)
  55. {
  56. tempY = contours[j].Y;
  57. tempX = contours[j].X;
  58. contours[j].X = contours[j + 1].X;
  59. contours[j + 1].X = tempX;
  60. }
  61. }
  62. int X = (int)(humanRoi.Width * 0.08);
  63. int Y = (int)(humanRoi.Height * 0.1);
  64. Point2D[] points = { new Point2D(tempX - X, tempY), new Point2D(tempX - X, tempY + Y) };
  65. return points;
  66. }
  67. /// <summary>
  68. /// 人体在X和Y方向的判断
  69. /// </summary>
  70. /// <param name="humanOrientationInPCS"></param>
  71. /// <param name="humanOrientationFlagX"></param>
  72. /// <param name="humanOrientationFlagY"></param>
  73. /// <returns></returns>
  74. private bool humanOrientationInPCSFlag(Point2D humanOrientationInPCS,out int humanOrientationFlagX, out int humanOrientationFlagY)
  75. {
  76. //每一张图都判断它的方向向量
  77. countSum++;
  78. humanOrientationFlagX=0;
  79. humanOrientationFlagY=0;
  80. if (humanOrientationInPCS.X > 0)
  81. {
  82. countXList.Add(1);
  83. }
  84. else
  85. {
  86. countXList.Add(0);
  87. }
  88. if (humanOrientationInPCS.Y > 0)
  89. {
  90. countYList.Add(1);
  91. }
  92. else
  93. {
  94. countYList.Add(0);
  95. }
  96. //多张图人体朝向概率
  97. if(countSum>15)
  98. {
  99. countXList.RemoveAt(0);
  100. countYList.RemoveAt(0);
  101. if (((float)countXList.Sum() / 15) > 0.5f)
  102. {
  103. humanOrientationFlagX = 1;
  104. }
  105. else
  106. {
  107. humanOrientationFlagX = 0;
  108. }
  109. if (((float)countYList.Sum() / 15) > 0.5f)
  110. {
  111. humanOrientationFlagY = 1;
  112. }
  113. else
  114. {
  115. humanOrientationFlagY = 0;
  116. }
  117. return true;
  118. }
  119. else
  120. {
  121. return false;
  122. }
  123. }
  124. /// <summary>
  125. /// 轮廓的中心点和外接框宽高
  126. /// </summary>
  127. /// <param name="organContours"></param>
  128. /// <param name="midX"></param>
  129. /// <param name="midY"></param>
  130. /// <param name="distanceX"></param>
  131. /// <param name="distanceY"></param>
  132. /// <returns></returns>
  133. private bool GetContourCenPoint(ContourPoints organContours,out int midX, out int midY,out int distanceX,out int distanceY)
  134. {
  135. midX = 0;
  136. midY = 0;
  137. distanceX=0;
  138. distanceY = 0;
  139. Point2D[] contours = (Point2D[])organContours.Points.Clone();
  140. int len = contours.Length;
  141. if (len == 0)
  142. {
  143. return false;
  144. }
  145. else
  146. {
  147. //轮廓中心点
  148. List<int> contoursX = new List<int>();
  149. List<int> contoursY = new List<int>();
  150. for (int i = 0; i < len; i++)
  151. {
  152. contoursX.Add(contours[i].X);
  153. contoursY.Add(contours[i].Y);
  154. }
  155. contoursX.Sort();
  156. contoursY.Sort();
  157. midX = (contoursX[0] + contoursX[len - 1]) / 2;
  158. midY = (contoursY[0] + contoursY[len - 1]) / 2;
  159. distanceX = (contoursX[len - 1] - contoursX[0]);
  160. distanceY = (contoursY[len - 1] - contoursY[0]);
  161. return true;
  162. }
  163. }
  164. /// <summary>
  165. /// 判断轮廓位置是否正常
  166. /// </summary>
  167. /// <param name="organContours"></param>
  168. /// <returns></returns>
  169. private bool SegPositionFlag(ContourPoints organContours)
  170. {
  171. int meanCountMidX, meanCountMidY;
  172. int midX=0;
  173. int midY = 0;
  174. int distanceX = 0;
  175. int distanceY = 0;
  176. bool isTureInSegContours = GetContourCenPoint(organContours, out midX, out midY, out distanceX, out distanceY);
  177. if(isTureInSegContours)
  178. {
  179. //多张图的轮廓中心点平均范围
  180. countMidXList.Add(midX);
  181. countMidYList.Add(midY);
  182. countList.Add(1);
  183. if (countMidXList.Count > 100)
  184. {
  185. countMidXList.RemoveRange(0, 50);
  186. countMidYList.RemoveRange(0, 50);
  187. countList.RemoveRange(0, 50);
  188. }
  189. meanCountMidX = countMidXList.Sum() / countList.Sum();
  190. meanCountMidY = countMidYList.Sum() / countList.Sum();
  191. if ((Math.Abs(countMidXList[countMidXList.Count - 1] - meanCountMidX) > distanceX / 2) || (Math.Abs(countMidYList[countMidXList.Count - 1] - meanCountMidY) > distanceY / 2))
  192. {
  193. return false;
  194. }
  195. else
  196. {
  197. return true;
  198. }
  199. }
  200. else
  201. {
  202. return false;
  203. }
  204. }
  205. /// <summary>
  206. /// 计算两点间距离
  207. /// </summary>
  208. /// <param name="x1"></param>
  209. /// <param name="y1"></param>
  210. /// <param name="x2"></param>
  211. /// <param name="y2"></param>
  212. /// <returns></returns>
  213. private float GetDistance(int x1,int y1,int x2,int y2)
  214. {
  215. float distance=(float)Math.Sqrt(Math.Pow(x1-x2,2) + Math.Pow(y1-y2,2));
  216. return distance;
  217. }
  218. /// <summary>
  219. /// 轮廓四个顶点
  220. /// </summary>
  221. /// <param name="contours"></param>
  222. /// <param name="midX"></param>
  223. /// <param name="midY"></param>
  224. /// <param name="flag"></param>
  225. /// <param name="pointX"></param>
  226. /// <param name="pointY"></param>
  227. private void GetPoints(Point2D[] contours,int midX,int midY,int flag, out int pointX, out int pointY)
  228. {
  229. int len = contours.Length;
  230. pointX = 0;
  231. pointY = 0;
  232. bool enable=false;
  233. for (int i = 0; i < len - 1; i++)
  234. {
  235. switch (flag)
  236. {
  237. case 1:
  238. enable = (contours[i + 1].X > midX && contours[i + 1].Y > midY);
  239. break;
  240. case 2:
  241. enable = (contours[i + 1].X < midX && contours[i + 1].Y < midY);
  242. break;
  243. case 3:
  244. enable = (contours[i + 1].X > midX && contours[i + 1].Y < midY);
  245. break;
  246. case 4:
  247. enable = (contours[i + 1].X < midX && contours[i + 1].Y > midY);
  248. break;
  249. default:
  250. break;
  251. }
  252. if (enable)
  253. {
  254. if (GetDistance(contours[i + 1].X, contours[i + 1].Y, midX, midY) < GetDistance(contours[i].X, contours[i].Y, midX, midY))
  255. {
  256. pointY = contours[i].Y;
  257. contours[i].Y = contours[i + 1].Y;
  258. contours[i + 1].Y = pointY;
  259. pointX = contours[i].X;
  260. contours[i].X = contours[i + 1].X;
  261. contours[i + 1].X = pointX;
  262. }
  263. }
  264. }
  265. }
  266. private Point2D[] GetHeartRoughSanPathInPCS(Point2D humanOrientationInPCS, Rect humanRoi, ContourPoints organContours)
  267. {
  268. Point2D[] result;
  269. int pointX1 = 0;
  270. int pointY1 = 0;
  271. int pointX2 = 0;
  272. int pointY2 = 0;
  273. int pointX3 = 0;
  274. int pointY3 = 0;
  275. int pointX4 = 0;
  276. int pointY4 = 0;
  277. int humanOrientationFlagX = 0;
  278. int humanOrientationFlagY=0;
  279. int midX = 0;
  280. int midY = 0;
  281. int distanceX = 0;
  282. int distanceY = 0;
  283. //轮廓是否存在,取中心点
  284. bool isTureInSegContours = GetContourCenPoint(organContours, out midX, out midY, out distanceX, out distanceY);
  285. //分割位置判断
  286. bool isTrueInSegPosition=SegPositionFlag(organContours);
  287. //人体朝向判断
  288. bool isDoneInHumanOrientation = humanOrientationInPCSFlag(humanOrientationInPCS, out humanOrientationFlagX, out humanOrientationFlagY);
  289. Point2D[] contours = (Point2D[])organContours.Points.Clone();
  290. if (!isTureInSegContours || !isTrueInSegPosition || !isDoneInHumanOrientation)
  291. {
  292. return null;
  293. }
  294. else
  295. {
  296. //得到轮廓距离中心点最远的四个点
  297. GetPoints(contours, midX, midY, 1, out pointX1, out pointY1);
  298. GetPoints(contours, midX, midY, 2, out pointX2, out pointY2);
  299. GetPoints(contours, midX, midY, 3, out pointX3, out pointY3);
  300. GetPoints(contours, midX, midY, 4, out pointX4, out pointY4);
  301. //长短轴距离
  302. float distance1 = GetDistance(pointX1, pointY1, midX, midY) + GetDistance(pointX2, pointY2, midX, midY);
  303. float distance2 = GetDistance(pointX3, pointY3, midX, midY) + GetDistance(pointX4, pointY4, midX, midY);
  304. //长短轴斜率
  305. float k1 = (float)(pointY2 - pointY1) / (pointX2 - pointX1);
  306. float k2 = (float)(pointY4 - pointY3) / (pointX4 - pointX3);
  307. if ((distance1 >= distance2)&&k1>0)
  308. {
  309. if (humanOrientationFlagY == 0)
  310. {
  311. Point2D[] points = { new Point2D(pointX1, pointY1), new Point2D(midX + distanceX/4, midY) };
  312. result = points;
  313. }
  314. else
  315. {
  316. Point2D[] points = { new Point2D(pointX2, pointY2), new Point2D(midX - distanceX/4, midY) };
  317. result = points;
  318. }
  319. }
  320. else if((distance1 <= distance2) && k2 < 0)
  321. {
  322. if (humanOrientationFlagX == 0)
  323. {
  324. Point2D[] points = { new Point2D(pointX3, pointY3), new Point2D(midX, midY + distanceY/4) };
  325. result = points;
  326. }
  327. else
  328. {
  329. Point2D[] points = { new Point2D(pointX4, pointY4), new Point2D(midX, midY - distanceY/4) };
  330. result = points;
  331. }
  332. }
  333. else
  334. {
  335. return null;
  336. }
  337. }
  338. return result;
  339. }
  340. #endregion
  341. }
  342. }