CarotidUpperIntimaMeasurement.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using Emgu.CV;
  6. using Emgu.CV.Structure;
  7. using Emgu.CV.CvEnum;
  8. using WingServerCommon.Log;
  9. namespace WingAIDiagnosisService.Carotid.Utilities.DetectIntima
  10. {
  11. /// <summary>
  12. /// 颈动脉上内膜检测
  13. /// </summary>
  14. public class CarotidUpperIntimaMeasurement : CarotidIntimaMeasurement
  15. {
  16. //磨平坑时修改的点个数
  17. private int _invalidPitPointsNum;
  18. //被平滑掉的点个数
  19. private int _invalidSmoothedPointNum;
  20. private CarotidIntimaMeasureParameter _measureParameter;
  21. private Image<Gray, byte> _imageRoiBinary;
  22. private Image<Gray, byte> _imageRoiCanny;
  23. private readonly List<Point> _upperPoint = new List<Point>();
  24. private readonly List<Point> _lowerPoint = new List<Point>();
  25. /// <summary>
  26. /// 上壁颈动脉自动测量对外接口
  27. /// </summary>
  28. /// <param name="measureParameter"></param>
  29. /// <returns></returns>
  30. public CarotidIntimaMeasureResult MeasureApi(CarotidIntimaMeasureParameter measureParameter)
  31. {
  32. if (measureParameter.Image == null)
  33. {
  34. return new CarotidIntimaMeasureResult(CarotidIntimaMeasureErrorCode.Failed);
  35. }
  36. var imageGray = measureParameter.Image.Copy();
  37. try
  38. {
  39. OptimizeImageQuality(imageGray, measureParameter.ImageProcessState.ContrastChanged,
  40. measureParameter.ImageProcessState.SharpnessChanged);
  41. var originalImageRectRoi = GetImageRoi(measureParameter.SelectRoi, imageGray.Size);
  42. var result = ImagePreprocessingUpper(imageGray, originalImageRectRoi, 0);
  43. if (result.IsSuccess)
  44. {
  45. return MeasureUpperWall(result.ImageRoiBinary,
  46. result.ImageRoiCanny,
  47. originalImageRectRoi,
  48. result.ImageRoiBinary.ROI,
  49. measureParameter.PhysicalPerPixel);
  50. }
  51. return new CarotidIntimaMeasureResult(CarotidIntimaMeasureErrorCode.Failed);
  52. }
  53. catch (Exception e)
  54. {
  55. Logger.WriteLineError("CarotidUpperIntimaMeasurement MeasureApi error." + e.Message + "," + e.StackTrace);
  56. return new CarotidIntimaMeasureResult(CarotidIntimaMeasureErrorCode.Failed);
  57. }
  58. finally
  59. {
  60. imageGray.Dispose();
  61. }
  62. }
  63. /// <summary>
  64. /// 内膜自动测量用的图像预处理
  65. /// </summary>
  66. /// <param name="measureParameter"></param>
  67. /// <returns></returns>
  68. public static Image<Gray, byte> ImagePreprocessing(CarotidIntimaMeasureParameter measureParameter)
  69. {
  70. var imageGray = measureParameter.Image.Copy();
  71. //优化图像质量
  72. OptimizeImageQuality(imageGray, measureParameter.ImageProcessState.ContrastChanged, measureParameter.ImageProcessState.SharpnessChanged);
  73. //图像预处理
  74. return imageGray;
  75. }
  76. /// <summary>
  77. /// 优化图像质量
  78. /// </summary>
  79. /// <param name="imageGray"></param>
  80. /// <param name="sharpnessChanged"></param>
  81. private static void OptimizeImageQuality(Image<Gray, byte> imageGray, bool contrastChanged, bool sharpnessChanged)
  82. {
  83. if (contrastChanged == false)
  84. {
  85. //contrastDegree = 1.5,brightness = -10;
  86. CvInvoke.cvConvertScale(imageGray, imageGray, 1.5, -10);
  87. }
  88. if (sharpnessChanged == false)
  89. {
  90. const int sharpFactor = 2;
  91. float[,] temp = { { 0, -sharpFactor, 0 }, { -sharpFactor, 1 + 4 * sharpFactor, -sharpFactor }, { 0, -sharpFactor, 0 } };
  92. var kernel = new ConvolutionKernelF(temp);
  93. CvInvoke.Filter2D(imageGray, imageGray, kernel, new Point(-1, -1));
  94. }
  95. }
  96. /// <summary>
  97. /// 上壁颈动脉自动测量
  98. /// </summary>
  99. /// <param name="imageGray"></param>
  100. /// <param name="rectRoi"></param>
  101. /// <returns></returns>
  102. public CarotidIntimaMeasureResult MeasureUpperWall(Image<Gray, byte> imageRoiBinary, Image<Gray, byte> imageRoiCanny, Rectangle originalImageRectRoi, Rectangle rectRoi, float physicalPerPixel)
  103. {
  104. try
  105. {
  106. //限制最小roi
  107. if (rectRoi.Width < 3 || rectRoi.Height < 3)
  108. {
  109. Logger.WriteLineError("CarotidUpperIntimaMeasurement MeasureUpperWall error." + "Selected roi is too small.");
  110. return new CarotidIntimaMeasureResult(CarotidIntimaMeasureErrorCode.Failed);
  111. }
  112. _upperPoint.Clear();
  113. _lowerPoint.Clear();
  114. _invalidPitPointsNum = 0;
  115. _invalidSmoothedPointNum = 0;
  116. PhysicalPerPixel = physicalPerPixel;
  117. var normalThick = UpperWallMaxIntimaThick * (1 / PhysicalPerPixel);
  118. MaxIntimaThickPix = Math.Min((int)normalThick, rectRoi.Height);
  119. MinIntimaThickPix = (int)(UpperMinIntimaThick * (1 / PhysicalPerPixel));
  120. _imageRoiBinary?.Dispose();
  121. _imageRoiCanny?.Dispose();
  122. _imageRoiBinary = imageRoiBinary.Copy(rectRoi);
  123. _imageRoiCanny = imageRoiCanny.Copy(rectRoi);
  124. //上壁检测算法
  125. var result1 = GetUpperMeasureCarotidPoint(originalImageRectRoi, ref rectRoi, MaxIntimaThickPix);
  126. //修改rect后再次回调
  127. if (result1 == 2)
  128. {
  129. return MeasureUpperWall(imageRoiBinary, imageRoiCanny, originalImageRectRoi, rectRoi,
  130. physicalPerPixel);
  131. }
  132. if (result1 != 0)
  133. {
  134. return new CarotidIntimaMeasureResult(CarotidIntimaMeasureErrorCode.Failed);
  135. }
  136. var result2 = GetDataStatistics(_upperPoint, _lowerPoint, _invalidPitPointsNum, _invalidSmoothedPointNum);
  137. if (result2.ErrorCode != CarotidIntimaMeasureErrorCode.Success)
  138. {
  139. return new CarotidIntimaMeasureResult(result2.ErrorCode);
  140. }
  141. //每个像素代表的毫米数
  142. double ratio = 10* PhysicalPerPixel;
  143. var upperMaxThickness = (float)(result2.MaxThick * ratio);
  144. var upperMinThickness = (float)(result2.MinThick * ratio);
  145. var upperAverageThickness = (float)(result2.AverageThick * ratio);
  146. var upperValidPointsNum = result2.ValidPointsNum;
  147. var upperSdThickness = result2.SdThickness;
  148. var std = result2.ThicknessStd;
  149. return new CarotidIntimaMeasureResult(CarotidIntimaMeasureErrorCode.Success, new List<Point>(_upperPoint),
  150. new List<Point>(_lowerPoint),
  151. upperMaxThickness, upperMinThickness, upperAverageThickness,
  152. upperSdThickness, upperValidPointsNum, std);
  153. }
  154. catch (Exception e)
  155. {
  156. Logger.WriteLineError("CarotidUpperIntimaMeasurement MeasureUpperWall error." + e.Message + "," + e.StackTrace);
  157. return new CarotidIntimaMeasureResult(CarotidIntimaMeasureErrorCode.Failed);
  158. }
  159. finally
  160. {
  161. _imageRoiCanny?.Dispose();
  162. _imageRoiBinary?.Dispose();
  163. }
  164. }
  165. /// <summary>
  166. /// 计算上壁内膜下边沿点
  167. /// </summary>
  168. /// <param name="imageCanny"></param>
  169. /// <returns></returns>
  170. private List<Point> GetOriginalLowerPoint(Image<Gray, byte> imageCanny)
  171. {
  172. RemoveImpurity(imageCanny);
  173. var lowerPointListTemp = new List<Point>();
  174. var dataList = new List<byte>();
  175. var width = imageCanny.Width;
  176. var height = imageCanny.Height;
  177. //获得每一列,从下往上第一个边缘点
  178. for (var w = 0; w < width; ++w)
  179. {
  180. dataList.Clear();
  181. for (var h = height - 1; h > -1; --h)
  182. {
  183. dataList.Add(imageCanny.Data[h, w, 0]);
  184. }
  185. var y1 = GetUpperIntimaLowerEdgePoints(dataList);
  186. lowerPointListTemp.Add(new Point(w, y1));
  187. }
  188. return lowerPointListTemp;
  189. }
  190. /// <summary>
  191. /// 颈动脉上内膜检测
  192. /// </summary>
  193. /// <param name="_imageRoiBinary"></param>
  194. /// <param name="_imageRoiCanny"></param>
  195. /// <param name="rectRoi"></param>
  196. /// <param name="thick"></param>
  197. /// <returns></returns>
  198. private int GetUpperMeasureCarotidPoint(Rectangle originalImageRectRoi, ref Rectangle rectRoi, int thick)
  199. {
  200. try
  201. {
  202. var upperWall = new List<Point>();
  203. var lowerWall = new List<Point>();
  204. var lowerPointListTemp = GetOriginalLowerPoint(_imageRoiCanny);
  205. //排除异常点---------------------------------
  206. ExcludeExceptionsOnePoint(lowerPointListTemp);
  207. ExcludeExceptionsPoints(lowerPointListTemp);
  208. //对下壁作平滑处理
  209. var smoothResult = PointsSmooth.SmoothLine(lowerPointListTemp);
  210. lowerPointListTemp = smoothResult.Points.ToList();
  211. _invalidSmoothedPointNum += smoothResult.InvalidNumber;
  212. //缩小上内膜下边缘下方的血管区域
  213. var maxY = lowerPointListTemp.Max(o => o.Y);
  214. if (_imageRoiBinary.Height - maxY > 10)
  215. {
  216. rectRoi = new Rectangle(rectRoi.Left, rectRoi.Top, rectRoi.Width, maxY + 9);
  217. return 2;
  218. }
  219. //求上壁
  220. var upperPointListTemp = GetUpperEdgePointsInUpperIntima(_imageRoiBinary, lowerPointListTemp, thick);
  221. if (upperPointListTemp.Count == 0)
  222. {
  223. return 1;
  224. }
  225. smoothResult = PointsSmooth.SmoothLineUpperWall(upperPointListTemp, lowerPointListTemp);
  226. upperPointListTemp = smoothResult.Points.ToList();
  227. _invalidSmoothedPointNum += smoothResult.InvalidNumber;
  228. RemoveInvalidUpperWallPoints(upperPointListTemp, lowerPointListTemp, out var smoothedNum3);
  229. _invalidSmoothedPointNum = _invalidSmoothedPointNum + smoothedNum3;
  230. //上下壁同时平滑处理
  231. var result1 = PointsSmooth.SmoothUpperIntimaTwoLine(upperPointListTemp, lowerPointListTemp, out var smoothedNum4);
  232. _invalidSmoothedPointNum = _invalidSmoothedPointNum + smoothedNum4;
  233. if (result1 != CarotidIntimaMeasureErrorCode.Success)
  234. {
  235. return 1;
  236. }
  237. var count = Math.Min(upperPointListTemp.Count, lowerPointListTemp.Count);
  238. //把小图中的点还原到ROI中正确坐标
  239. for (var i = 0; i < count; ++i)
  240. {
  241. var upperPointY = Math.Max(upperPointListTemp[i].Y, 0);
  242. var lowerPointY = Math.Min(lowerPointListTemp[i].Y, rectRoi.Height - 1);
  243. upperWall.Add(new Point(upperPointListTemp[i].X + rectRoi.Left, upperPointY + rectRoi.Top));
  244. lowerWall.Add(new Point(lowerPointListTemp[i].X + rectRoi.Left, lowerPointY + rectRoi.Top));
  245. }
  246. //把ROI中的点还原到原始图中正确坐标
  247. _upperPoint.Clear();
  248. _lowerPoint.Clear();
  249. for (var i = 0; i < count; ++i)
  250. {
  251. var upperPointY = Math.Max(upperWall[i].Y, 0);
  252. var lowerPointY = Math.Min(lowerWall[i].Y, originalImageRectRoi.Height - 1);
  253. _upperPoint.Add(new Point(upperPointListTemp[i].X + originalImageRectRoi.Left, upperPointY + originalImageRectRoi.Top));
  254. _lowerPoint.Add(new Point(lowerPointListTemp[i].X + originalImageRectRoi.Left, lowerPointY + originalImageRectRoi.Top));
  255. }
  256. return 0;
  257. }
  258. catch (Exception e)
  259. {
  260. Logger.WriteLineError("CarotidUpperIntimaMeasurement GetUpperMeasureCarotidPoint error." + e.Message + "," + e.StackTrace);
  261. return 1;
  262. }
  263. }
  264. /// <summary>
  265. /// 去除掉下壁中的异常点
  266. /// </summary>
  267. /// <param name="upperPointListTemp"></param>
  268. /// <param name="lowerPointListTemp"></param>
  269. /// <param name="num"></param>
  270. private void RemoveInvalidUpperWallPoints(IList<Point> upperPointListTemp,
  271. IReadOnlyList<Point> lowerPointListTemp, out int num)
  272. {
  273. num = 0;
  274. var count = lowerPointListTemp.Count;
  275. for (var i = 0; i < count; ++i)
  276. {
  277. if (upperPointListTemp[i].Y <= Math.Max(lowerPointListTemp[i].Y - MinIntimaThickPix, 0)) continue;
  278. upperPointListTemp[i] = new Point(upperPointListTemp[i].X, Math.Max(lowerPointListTemp[i].Y - MinIntimaThickPix, 0));
  279. num++;
  280. }
  281. }
  282. /// <summary>
  283. /// 求上内膜时,求上壁边缘点
  284. /// </summary>
  285. /// <param name="imageRoiBinary"></param>
  286. /// <param name="lowerWallPoints"></param>
  287. /// <param name="thick"></param>
  288. /// <returns></returns>
  289. private List<Point> GetUpperEdgePointsInUpperIntima(Image<Gray, byte> imageRoiBinary, IReadOnlyList<Point> lowerWallPoints, int thick)
  290. {
  291. try
  292. {
  293. if (thick <= 0)
  294. {
  295. return new List<Point>();
  296. }
  297. if (imageRoiBinary.Height < MinRoiHeight)
  298. {
  299. return new List<Point>();
  300. }
  301. thick = (MinIntimaThickPix + thick) / 2;
  302. var upperWallPoints = lowerWallPoints.Select(point => new Point(point.X, Math.Max(0, point.Y - thick))).ToList();
  303. //微调上边缘点
  304. var res = UpperIntimaUpperEdgePointTrim(imageRoiBinary, upperWallPoints, lowerWallPoints);
  305. return res != CarotidIntimaMeasureErrorCode.Success ? new List<Point>() : upperWallPoints;
  306. }
  307. catch (Exception e)
  308. {
  309. Logger.WriteLineError("CarotidUpperIntimaMeasurement GetUpperEdgePointsInUpperIntima error." + e.Message + "," + e.StackTrace);
  310. return new List<Point>();
  311. }
  312. }
  313. /// <summary>
  314. /// 颈动脉上内膜,上壁点微调
  315. /// </summary>
  316. /// <param name="imageRoiBinary"></param>
  317. /// <param name="upperWall"></param>
  318. /// <param name="lowerWall"></param>
  319. /// <returns></returns>
  320. private CarotidIntimaMeasureErrorCode UpperIntimaUpperEdgePointTrim(Image<Gray, byte> imageRoiBinary, List<Point> upperWall, IReadOnlyList<Point> lowerWall)
  321. {
  322. try
  323. {
  324. var trimRange = (MaxIntimaThickPix - MinIntimaThickPix) / 2;
  325. var tempList = new List<Point>();
  326. for (var i = 0; i < upperWall.Count; ++i)
  327. {
  328. var point = upperWall[i];
  329. var xValue = point.X;
  330. var startYValue = Math.Min(lowerWall[i].Y, point.Y + trimRange);
  331. var endYValue = Math.Max(0, point.Y - trimRange);
  332. if (endYValue == startYValue)
  333. {
  334. tempList.Add(upperWall[i]);
  335. continue;
  336. }
  337. var count = startYValue - endYValue + 1;
  338. var yRange = new int[count];
  339. for (var j = 0; j < count; ++j)
  340. {
  341. yRange[j] = Math.Max(startYValue - j, 0);
  342. }
  343. var grayValue = new byte[count];
  344. for (var m = 0; m < grayValue.Length; ++m)
  345. {
  346. grayValue[m] = imageRoiBinary.Data[yRange[m], xValue, 0];
  347. }
  348. //求变化率----------------------------------------------------------------------------
  349. var grayDiff = new int[count - 1];
  350. for (var n = 0; n < grayDiff.Length; ++n)
  351. {
  352. grayDiff[n] = grayValue[n + 1] - grayValue[n];
  353. }
  354. var maxDiff = 0;
  355. var maxId = 0;
  356. var isFind = false;
  357. //找到变化率最大的
  358. for (var n = 0; n < grayDiff.Length; ++n)
  359. {
  360. var temp = grayDiff[n];
  361. if (temp <= maxDiff) continue;
  362. maxDiff = temp;
  363. maxId = n;
  364. isFind = true;
  365. }
  366. for (var m = 0; m < grayValue.Length; ++m)
  367. {
  368. if (grayValue[m] > ImageThreshold)
  369. {
  370. grayValue[m] = 255;
  371. }
  372. grayValue[m] = 0;
  373. }
  374. tempList.Add(isFind ? new Point(lowerWall[i].X, yRange[maxId]) : lowerWall[i]);
  375. }
  376. upperWall.Clear();
  377. upperWall.AddRange(tempList);
  378. return CarotidIntimaMeasureErrorCode.Success;
  379. }
  380. catch (Exception e)
  381. {
  382. Logger.WriteLineError("CarotidUpperIntimaMeasurement UpperIntimaUpperEdgePointTrim error." + e.Message + "," + e.StackTrace);
  383. return CarotidIntimaMeasureErrorCode.Failed;
  384. }
  385. }
  386. /// <summary>
  387. /// 求上内膜下壁边缘点
  388. /// </summary>
  389. /// <param name="dataList"></param>
  390. private static int GetUpperIntimaLowerEdgePoints(IReadOnlyList<byte> dataList)
  391. {
  392. var y1 = 0;
  393. var count = dataList.Count;
  394. //找到变化最大的两个点
  395. for (var i = 0; i < count; ++i)
  396. {
  397. if (dataList[i] <= 10) continue;
  398. y1 = i + 1;
  399. break;
  400. }
  401. return count - y1;
  402. }
  403. /// <summary>
  404. /// 图像初始化
  405. /// </summary>
  406. /// <param name="imageGray"></param>
  407. /// <param name="rectRoi"></param>
  408. /// <param name="subtractTheThreshold"></param>
  409. /// <returns></returns>
  410. public ImagePreprocessingResult ImagePreprocessingUpper(Image<Gray, byte> imageGray, Rectangle rectRoi, int subtractTheThreshold)
  411. {
  412. try
  413. {
  414. var imageRoiBinary = imageGray.Copy(rectRoi);
  415. //求二值化阈值-----------------------------------------------------------------------------------
  416. var threshold = ImageTools.GetThreshold(imageRoiBinary);
  417. threshold -= subtractTheThreshold;
  418. if (threshold < 0)
  419. {
  420. threshold = 0;
  421. }
  422. ImageThreshold = threshold;
  423. //另一二值化的图像
  424. var imageRoiCanny = new Image<Gray, byte>(imageRoiBinary.Width, imageRoiBinary.Height);
  425. //二值化
  426. CvInvoke.Threshold(imageRoiBinary, imageRoiCanny, threshold, 255, ThresholdType.ToZero);
  427. return new ImagePreprocessingResult(imageRoiBinary, imageRoiCanny, true);
  428. }
  429. catch (Exception e)
  430. {
  431. Logger.WriteLineError("CarotidUpperIntimaMeasurement ImagePreprocessingUpper error." + e.Message + "," + e.StackTrace);
  432. //图像预处理过程出错
  433. return new ImagePreprocessingResult(false);
  434. }
  435. }
  436. /// <summary>
  437. /// 去掉异常的一个点
  438. /// </summary>
  439. /// <param name="wallPointList"></param>
  440. private void ExcludeExceptionsOnePoint(List<Point> wallPointList)
  441. {
  442. try
  443. {
  444. var length = wallPointList.Count;
  445. if (length < 3)
  446. {
  447. return;
  448. }
  449. const int threshold = 2;
  450. var temp = new List<Point>();
  451. var firstPointY = wallPointList[0].Y;
  452. var secondPointY = wallPointList[1].Y;
  453. if (Math.Abs(firstPointY - secondPointY) > threshold)
  454. {
  455. wallPointList[0] = new Point(wallPointList[0].X, secondPointY);
  456. _invalidSmoothedPointNum++;
  457. }
  458. temp.Add(new Point(wallPointList[0].X, secondPointY));
  459. for (var i = 1; i < length - 1; ++i)
  460. {
  461. var pointY = wallPointList[i].Y;
  462. var beforePointY = wallPointList[i - 1].Y;
  463. var nextPointY = wallPointList[i + 1].Y;
  464. if (Math.Abs(pointY - beforePointY) > 2 && Math.Abs(pointY - nextPointY) > threshold)
  465. {
  466. temp.Add(new Point(wallPointList[i].X, (beforePointY + nextPointY) / 2));
  467. _invalidSmoothedPointNum++;
  468. }
  469. else
  470. {
  471. temp.Add(new Point(wallPointList[i].X, wallPointList[i].Y));
  472. }
  473. }
  474. var lastPointY = wallPointList.Last().Y;
  475. if (Math.Abs(lastPointY - wallPointList[length - 1].Y) > threshold)
  476. {
  477. temp.Add(new Point(wallPointList[length - 1].X, wallPointList[length - 1].Y));
  478. _invalidSmoothedPointNum++;
  479. }
  480. else
  481. {
  482. temp.Add(wallPointList.Last());
  483. }
  484. wallPointList.Clear();
  485. wallPointList.AddRange(temp);
  486. }
  487. catch (Exception e)
  488. {
  489. Logger.WriteLineError("CarotidUpperIntimaMeasurement ExcludeExceptionsOnePoint error." + e.Message + "," + e.StackTrace);
  490. }
  491. }
  492. /// <summary>
  493. /// 去掉异常的多个点
  494. /// </summary>
  495. /// <param name="wallPointList"></param>
  496. private void ExcludeExceptionsPoints(IList<Point> wallPointList)
  497. {
  498. try
  499. {
  500. var length = wallPointList.Count;
  501. if (length < 3)
  502. {
  503. return;
  504. }
  505. //把list分段
  506. var sectionList = new List<List<Point>>();
  507. var beginIndex = 0;
  508. for (var i = 1; i < length; ++i)
  509. {
  510. if (Math.Abs(wallPointList[i].Y - wallPointList[i - 1].Y) <= 2) continue;
  511. sectionList.Add(wallPointList.Skip(beginIndex).Take(i - beginIndex).ToList());
  512. beginIndex = i;
  513. }
  514. sectionList.Add(wallPointList.Skip(beginIndex).Take(length - beginIndex).ToList());
  515. if (beginIndex == 0)
  516. {
  517. return;
  518. }
  519. //比较前两个区域
  520. var num1 = sectionList[0].Count;
  521. var num2 = sectionList[1].Count;
  522. var changePointList = new List<Point>();
  523. var newY = 0;
  524. if (num1 < num2)
  525. {
  526. changePointList = sectionList[0];
  527. newY = sectionList[1][0].Y;
  528. }
  529. if (num1 == num2)
  530. {
  531. if (sectionList[0].Last().Y > sectionList[1][0].Y)
  532. {
  533. changePointList = sectionList[1];
  534. newY = sectionList[0].Last().Y;
  535. }
  536. else
  537. {
  538. changePointList = sectionList[0];
  539. newY = sectionList[1][0].Y;
  540. }
  541. }
  542. if (num1 > num2)
  543. {
  544. changePointList = sectionList[1];
  545. newY = sectionList[0].Last().Y;
  546. }
  547. _invalidSmoothedPointNum += changePointList.Count;
  548. foreach (var point in changePointList)
  549. {
  550. wallPointList[point.X] = new Point(point.X, newY);
  551. }
  552. ExcludeExceptionsPoints(wallPointList);
  553. }
  554. catch (Exception e)
  555. {
  556. Logger.WriteLineError("CarotidUpperIntimaMeasurement ExcludeExceptionsPoints error." + e.Message + "," + e.StackTrace);
  557. }
  558. }
  559. }
  560. }