ImageInfo.xaml.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Documents;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using System.Windows.Media.Imaging;
  13. using System.Windows.Navigation;
  14. using System.Windows.Shapes;
  15. using System.Drawing;
  16. using AI.Common;
  17. using AutoEFInferenceCalcLib;
  18. using System.Windows.Threading;
  19. using ImageShowUtilsLib;
  20. using System.Collections.Concurrent;
  21. using Newtonsoft.Json;
  22. namespace AutoEFCalculationDemo
  23. {
  24. /// <summary>
  25. /// 界面大小变化
  26. /// </summary>
  27. public class MyTransform
  28. {
  29. public double Scale { get; set; }
  30. public double OffsetX { get; set; }
  31. public double OffsetY { get; set; }
  32. public MyTransform(double scale, double offsetX, double offsetY)
  33. {
  34. Scale = scale;
  35. OffsetX = offsetX;
  36. OffsetY = offsetY;
  37. }
  38. public System.Windows.Point Transform(System.Windows.Point point)
  39. {
  40. double x = OffsetX + Scale * point.X;
  41. double y = OffsetY + Scale * point.Y;
  42. return new System.Windows.Point(x, y);
  43. }
  44. public System.Windows.Rect Transform(System.Windows.Rect rect)
  45. {
  46. double left = OffsetX + Scale * rect.Left;
  47. double top = OffsetY + Scale * rect.Top;
  48. double width = Scale * rect.Width;
  49. double height = Scale * rect.Height;
  50. return new System.Windows.Rect(left, top, width, height);
  51. }
  52. }
  53. internal class Roi
  54. {
  55. internal AI.Common.Rect BoundingBox { get; set; }
  56. internal System.Windows.Media.Brush Color { get; set; }
  57. internal Point2D[] Contour { get; set; }
  58. internal string LabelName { get; set; }
  59. internal Roi(Point2D[] contour, System.Windows.Media.Brush color, string labelName)
  60. {
  61. Contour = contour;
  62. LabelName = labelName;
  63. Color = color;
  64. }
  65. }
  66. public class Organ
  67. {
  68. public string OrganName { get; set; }
  69. public AI.Common.Rect BoundingBox { get; set; }
  70. public Point2D[][] Contour { get; set; }
  71. public System.Windows.Media.Brush Color => System.Windows.Media.Brushes.Green;
  72. public Organ(string organName, AI.Common.Rect boundBox, Point2D[][] contour)
  73. {
  74. OrganName = organName;
  75. BoundingBox = boundBox;
  76. Contour = contour;
  77. }
  78. }
  79. /// <summary>
  80. /// ImageInfo.xaml 的交互逻辑
  81. /// </summary>
  82. public partial class ImageInfo : UserControl
  83. {
  84. #region private
  85. private volatile bool _enableAI;
  86. private volatile bool _enableShowObjectContour;
  87. private volatile bool _enableShowMeasureLine;
  88. private volatile bool _enableShowMeasureCurve;
  89. private volatile bool _enableShowTimeSeriesResult;
  90. private Bitmap _image;
  91. private MyTransform _transform;
  92. private List<Roi> _rois;
  93. private CardiacCurveInfos _cardiacCurveInfos;
  94. private MeasureCurveInfo _measureCurve = new MeasureCurveInfo(10000, 1000, 0, 200, 40.0,new List<string> {"AutoEF.Volume", "AutoEF.CardiacCycle" });
  95. private ConcurrentDictionary<double, Bitmap> _imageInfo = new ConcurrentDictionary<double, Bitmap>();
  96. private Dictionary<double, LVVolumeCalcResult> _hasShow = new Dictionary<double, LVVolumeCalcResult>();
  97. #endregion
  98. #region properties
  99. private void CanvasChangeSize(object sender, SizeChangedEventArgs e)
  100. {
  101. RoiCanvas.Width = GridOrigImg.ActualWidth;
  102. RoiCanvas.Height = GridOrigImg.ActualHeight;
  103. UpdateTransforms();
  104. UpdateRois();
  105. UpdateShowMeasureLine();
  106. UpdateTimeSeriesResultPanelItems();
  107. }
  108. #endregion
  109. #region public func
  110. public ImageInfo()
  111. {
  112. InitializeComponent();
  113. }
  114. public void SetImageShowsParam(bool enableAI, bool showObject)
  115. {
  116. _enableAI = enableAI;
  117. _enableShowObjectContour = showObject;
  118. if(_rois != null)
  119. {
  120. UpdateRois();
  121. }
  122. if(_cardiacCurveInfos != null)
  123. {
  124. UpdateShowMeasureLine();
  125. }
  126. }
  127. public void SetShowMeasureLine(bool showMeasureLine)
  128. {
  129. _enableShowMeasureLine = showMeasureLine;
  130. if( _rois != null)
  131. {
  132. UpdateRois();
  133. }
  134. if(_cardiacCurveInfos != null)
  135. {
  136. UpdateShowMeasureLine();
  137. }
  138. }
  139. public void SetShowTimeSeriesResult(bool showTimeSeriesResult)
  140. {
  141. _enableShowTimeSeriesResult = showTimeSeriesResult;
  142. if( _rois != null)
  143. {
  144. UpdateRois();
  145. }
  146. if (_cardiacCurveInfos != null)
  147. {
  148. UpdateShowMeasureLine();
  149. }
  150. //if ( _cardiacCurveInfos != null)
  151. //{
  152. // UpdateTimeSeriesResultPanelItems();
  153. //}
  154. //if( _cardiacCurveInfos != null)
  155. //{
  156. // UpdateShowMeasureCurve();
  157. //}
  158. }
  159. public void SetShowMeasureCurve(bool showMeasureCurve)
  160. {
  161. _enableShowMeasureCurve = showMeasureCurve;
  162. if( _rois != null)
  163. {
  164. UpdateRois();
  165. }
  166. if( _cardiacCurveInfos != null)
  167. {
  168. UpdateShowMeasureLine();
  169. }
  170. }
  171. public void UpdateImage(double frameTime, Bitmap image)
  172. {
  173. _image = image.Clone(new System.Drawing.Rectangle(0,0,image.Width, image.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb);
  174. _imageInfo.TryAdd(frameTime, _image);
  175. //更新缩放比例
  176. UpdateTransforms();
  177. //更新图像显示
  178. var bitmapImage = RawImageShowUtils.BitmapToBitmapImage(_image);
  179. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
  180. {
  181. ImageShow.Source = bitmapImage;
  182. }));
  183. }
  184. public void UpdateDiagResult(string dataID, double currentTimeStamp, CardiacCurveInfos cardiacCurveInfos = null)
  185. {
  186. List<Roi> rois = new List<Roi>();
  187. LVVolumeCalcResult detectResult =cardiacCurveInfos.ResultPerImage.Last().Value;
  188. if(detectResult.Contour != null)
  189. {
  190. string labelName = "左心室内轮廓";
  191. System.Windows.Media.Brush brush = System.Windows.Media.Brushes.DodgerBlue;
  192. Roi roi = new Roi(detectResult.Contour, brush, labelName);
  193. rois.Add(roi);
  194. }
  195. //删掉旧的Roi和Organ
  196. RemoveMaesureLine();
  197. RemoveRois();
  198. RemoveMeasureCurve();
  199. //RemoveTimeSeriesResult();
  200. //设置
  201. _rois = rois;
  202. _cardiacCurveInfos = cardiacCurveInfos;
  203. //更新画布上显示的Roi
  204. UpdateRois();
  205. UpdateShowMeasureLine();
  206. UpdateShowMeasureCurve(dataID, currentTimeStamp);
  207. UpdateTimeSeriesResultPanelItems();
  208. }
  209. public void ClearDiagResult()
  210. {
  211. //删掉已有的Roi
  212. RemoveRois();
  213. RemoveMaesureLine() ;
  214. RemoveMeasureCurve();
  215. RemoveTimeSeriesResult();
  216. //设置
  217. _rois = null;
  218. _cardiacCurveInfos = null;
  219. _measureCurve.ClaerResult();
  220. _hasShow.Clear();
  221. _imageInfo.Clear();
  222. }
  223. #endregion
  224. #region Draw
  225. /// <summary>
  226. /// 在画布上画出轮廓
  227. /// </summary>
  228. /// <param name="roi"></param>
  229. /// <param name="roiIndex"></param>
  230. private void DrawRoiInCanvas(Roi roi, string roiIndex)
  231. {
  232. if(_transform == null)
  233. {
  234. return;
  235. }
  236. RemoveRoiInCanvas(roiIndex);
  237. //如果不启用AI,则直接退出‘
  238. if(!_enableAI)
  239. {
  240. return;
  241. }
  242. //直接画轮廓
  243. if(_enableShowObjectContour)
  244. {
  245. if(roi.Contour?.Length <= 0)
  246. {
  247. return;
  248. }
  249. PointCollection contourPoint = new PointCollection();
  250. for(int i = 0; i < roi.Contour.Length; i++)
  251. {
  252. var point = new System.Windows.Point(roi.Contour[i].X, roi.Contour[i].Y);
  253. var transPoint = _transform.Transform(point);
  254. contourPoint.Add(transPoint);
  255. }
  256. //画出识别到的目标的结构
  257. System.Windows.Shapes.Polyline contourDraw = new System.Windows.Shapes.Polyline();
  258. contourDraw.Points = contourPoint;
  259. contourDraw.StrokeThickness = 2;
  260. contourDraw.Stroke = roi.Color;
  261. RoiCanvas.Children.Add(contourDraw);
  262. string roiName = "Roi_Contour" + roiIndex;
  263. RoiCanvas.RegisterName(roiName, contourDraw);
  264. //画出心肌末端的连线
  265. System.Windows.Shapes.Line endLine = new System.Windows.Shapes.Line();
  266. endLine.X1 = contourPoint[0].X;
  267. endLine.Y1 = contourPoint[0].Y;
  268. endLine.X2 = contourPoint[contourPoint.Count - 1].X;
  269. endLine.Y2 = contourPoint[contourPoint.Count - 1].Y;
  270. endLine.StrokeThickness = 2;
  271. endLine.Stroke = roi.Color;
  272. RoiCanvas.Children.Add(endLine);
  273. string lineName = "EndLine" + roiIndex;
  274. RoiCanvas.RegisterName(lineName, endLine);
  275. //TODO:显示识别部位的名称
  276. }
  277. }
  278. private void DrawMeasureLines(CardiacCurveInfos curveInfos)
  279. {
  280. if(_transform == null) { return;}
  281. //已有则删除
  282. RemoveMaesureLine();
  283. //若不启用AI则退出
  284. if(!_enableAI)
  285. {
  286. return;
  287. }
  288. LVVolumeCalcResult resultPerImage = curveInfos.ResultPerImage.Last().Value;
  289. if (resultPerImage == LVVolumeCalcResult.Empty)
  290. {
  291. return;
  292. }
  293. //画测量线
  294. if (_enableShowMeasureLine)
  295. {
  296. //显示切片点
  297. PointCollection slicePoints = new PointCollection();
  298. var slicePointOri = resultPerImage.MeasureMarks.SlicePoint;
  299. var controlPointOri = resultPerImage.MeasureMarks.ControlPoints;
  300. for (int i = 0; i < slicePointOri.Length; i++)
  301. {
  302. var slicePoint = new System.Windows.Point(slicePointOri[i].X, slicePointOri[i].Y);
  303. slicePoints.Add(slicePoint);
  304. }
  305. //显示切片连线
  306. for(int i = 0; i < slicePointOri.Length / 2; i++)
  307. {
  308. var transPoint1 = _transform.Transform(slicePoints[2 * i]);
  309. var transPoint2 = _transform.Transform(slicePoints[2 * i + 1]);
  310. System.Windows.Shapes.Line sliceLine = new System.Windows.Shapes.Line();
  311. sliceLine.X1 = transPoint1.X;
  312. sliceLine.Y1 = transPoint1.Y;
  313. sliceLine.X2 = transPoint2.X;
  314. sliceLine.Y2 = transPoint2.Y;
  315. sliceLine.StrokeThickness = 1;
  316. sliceLine.Stroke = System.Windows.Media.Brushes.Coral;
  317. RoiCanvas.Children.Add(sliceLine);
  318. string lineName = "MeasureLine_" + i.ToString();
  319. RoiCanvas.RegisterName(lineName, sliceLine);
  320. }
  321. //显示控制点
  322. for(int i = 0; i < controlPointOri.Length; i++)
  323. {
  324. var controlPoint = new System.Windows.Point(controlPointOri[i].X, controlPointOri[i].Y);
  325. var transPoint = _transform.Transform(controlPoint);
  326. System.Windows.Shapes.Path circleDraw = new System.Windows.Shapes.Path();
  327. EllipseGeometry ellipseGeometry = new EllipseGeometry();
  328. ellipseGeometry.Center = transPoint;
  329. ellipseGeometry.RadiusX = 3;
  330. ellipseGeometry.RadiusY = 3;
  331. circleDraw.Data = ellipseGeometry;
  332. circleDraw.Fill = System.Windows.Media.Brushes.DarkRed;
  333. RoiCanvas.Children.Add(circleDraw);
  334. string circleName = "ControlPoint_" + i.ToString();
  335. RoiCanvas.RegisterName(circleName, circleDraw);
  336. }
  337. //显示左心室中轴线
  338. var apexPoint = new System.Windows.Point(resultPerImage.MeasureMarks.ApexPoint.X,
  339. resultPerImage.MeasureMarks.ApexPoint.Y);
  340. var endPoints = resultPerImage.MeasureMarks.EndPoints;
  341. System.Windows.Point centerPoint = new System.Windows.Point();
  342. centerPoint.X = (endPoints[0].X + endPoints[1].X) / 2;
  343. centerPoint.Y = (endPoints[0].Y + endPoints[1].Y) / 2;
  344. var transApexPoint = _transform.Transform(apexPoint);
  345. var transCenterPoint = _transform.Transform(centerPoint);
  346. System.Windows.Shapes.Line axisLine = new System.Windows.Shapes.Line();
  347. axisLine.X1 = transApexPoint.X;
  348. axisLine.Y1 = transApexPoint.Y;
  349. axisLine.X2 = transCenterPoint.X;
  350. axisLine.Y2 = transCenterPoint.Y;
  351. axisLine.StrokeThickness = 1;
  352. axisLine.Stroke = System.Windows.Media.Brushes.Coral;
  353. RoiCanvas.Children.Add(axisLine);
  354. string axisLineName = "AxisLine";
  355. RoiCanvas.RegisterName(axisLineName, axisLine);
  356. }
  357. }
  358. #endregion
  359. #region remove
  360. /// <summary>
  361. /// 删除Roi轮廓
  362. /// </summary>
  363. /// <param name="roiIndex"></param>
  364. private void RemoveRoiInCanvas(string roiIndex)
  365. {
  366. //删除轮廓
  367. string contourName = "Roi_Contour" + roiIndex;
  368. System.Windows.Shapes.Polyline contourExist = RoiCanvas.FindName(contourName) as System.Windows.Shapes.Polyline;
  369. if (contourExist != null)
  370. {
  371. RoiCanvas.Children.Remove(contourExist);
  372. RoiCanvas.UnregisterName(contourName);
  373. }
  374. string lineName = "EndLine" + roiIndex;
  375. System.Windows.Shapes.Line lineExist = RoiCanvas.FindName(lineName) as System.Windows.Shapes.Line;
  376. if(lineExist != null)
  377. {
  378. RoiCanvas.Children.Remove(lineExist);
  379. RoiCanvas.UnregisterName(lineName);
  380. }
  381. }
  382. private void RemoveMaesure()
  383. {
  384. //删除测量线
  385. for (int i = 0; i < _cardiacCurveInfos.ResultPerImage.Last().Value.MeasureMarks.SlicePoint.Length / 2; i++)
  386. {
  387. string measureLineName = "MeasureLine_" + i.ToString();
  388. System.Windows.Shapes.Line lineExist = RoiCanvas.FindName(measureLineName) as System.Windows.Shapes.Line;
  389. if (lineExist != null)
  390. {
  391. RoiCanvas.Children.Remove(lineExist);
  392. RoiCanvas.UnregisterName(measureLineName);
  393. }
  394. }
  395. //删除控制点
  396. for(int i = 0; i < _cardiacCurveInfos.ResultPerImage.Last().Value.MeasureMarks.ControlPoints.Length; i++)
  397. {
  398. string circleName = "ControlPoint_" + i.ToString();
  399. System.Windows.Shapes.Path circleExist = RoiCanvas.FindName(circleName) as System.Windows.Shapes.Path;
  400. if (circleExist != null)
  401. {
  402. RoiCanvas.Children.Remove(circleExist);
  403. RoiCanvas.UnregisterName(circleName);
  404. }
  405. }
  406. //删除中轴线
  407. string axisLineName = "AxisLine";
  408. System.Windows.Shapes.Line axisLineExist = RoiCanvas.FindName(axisLineName) as System.Windows.Shapes.Line;
  409. if (axisLineExist != null)
  410. {
  411. RoiCanvas.Children.Remove(axisLineExist);
  412. RoiCanvas.UnregisterName(axisLineName);
  413. }
  414. }
  415. private void RemoveRois()
  416. {
  417. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  418. {
  419. if(_rois != null)
  420. {
  421. for(int i = 0; i < _rois.Count;i++)
  422. {
  423. RemoveRoiInCanvas(i.ToString());
  424. }
  425. }
  426. }));
  427. }
  428. private void RemoveMaesureLine()
  429. {
  430. Dispatcher.Invoke((Action)(() =>
  431. {
  432. if(_cardiacCurveInfos != null)
  433. {
  434. RemoveMaesure();
  435. }
  436. }));
  437. }
  438. private void RemoveMeasureCurve()
  439. {
  440. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  441. {
  442. PanelMeasureCurves.Children.Clear();
  443. }));
  444. }
  445. private void RemoveTimeSeriesResult()
  446. {
  447. Dispatcher.Invoke(() =>
  448. {
  449. PanelTimeSeriesBasedResults.Children.Clear();
  450. });
  451. }
  452. #endregion
  453. #region private
  454. private void UpdateTransforms()
  455. {
  456. if(_image != null)
  457. {
  458. var imgWidth = _image.Width;
  459. var imgHeight = _image.Height;
  460. var canvasWidth = GridOrigImg.ActualWidth;
  461. var canvasHeight = GridOrigImg.ActualHeight;
  462. var scaleX = canvasWidth / imgWidth;
  463. var scaleY = canvasHeight / imgHeight;
  464. var scale = scaleX < scaleY ? scaleX : scaleY;
  465. double offsetX, offsetY;
  466. if (Math.Abs(scale - scaleX) < 0.0001)
  467. {
  468. offsetY = 0.5 * (scaleY - scale) * imgHeight;
  469. offsetX = 0;
  470. }
  471. else
  472. {
  473. offsetX = 0.5 * (scaleX - scale) * imgWidth;
  474. offsetY = 0;
  475. }
  476. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  477. {
  478. //更新画布尺寸,使其刚好只覆盖图像区域
  479. RoiCanvas.Width = scale * _image.Width;
  480. RoiCanvas.Height = scale * _image.Height;
  481. Canvas.SetLeft(RoiCanvas, offsetX);
  482. Canvas.SetTop(RoiCanvas, offsetY);
  483. OrigImgScaleTransform.CenterX = 0;
  484. OrigImgScaleTransform.CenterY = 0;
  485. OrigImgScaleTransform.ScaleX = scale;
  486. OrigImgScaleTransform.ScaleY = scale;
  487. }));
  488. _transform = new MyTransform(scale, 0, 0);
  489. }
  490. }
  491. private void UpdateRois()
  492. {
  493. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  494. {
  495. if(_rois != null)
  496. {
  497. for(int i = 0; i < _rois.Count; i++)
  498. {
  499. DrawRoiInCanvas(_rois[i], i.ToString());
  500. }
  501. }
  502. }));
  503. }
  504. private void UpdateShowMeasureLine()
  505. {
  506. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  507. {
  508. if(_cardiacCurveInfos != null)
  509. {
  510. DrawMeasureLines(_cardiacCurveInfos);
  511. }
  512. }));
  513. }
  514. private void UpdateShowMeasureCurve(string dataID, double currentTimeStamp)
  515. {
  516. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  517. {
  518. var curve = new CurveInfo(_measureCurve);
  519. PanelMeasureCurves.Children.Add(curve);
  520. List<Dictionary<double, LVVolumeCalcResult>> cardiacCurveInfos = new List<Dictionary<double, LVVolumeCalcResult>>();
  521. cardiacCurveInfos.Add(_cardiacCurveInfos.ResultPerImage);
  522. CardiacCycleInfos[] cardiacCycles = _cardiacCurveInfos.CardiacCycles;
  523. _measureCurve.UpdateCurveResult(dataID, currentTimeStamp, cardiacCurveInfos, cardiacCycles);
  524. }));
  525. }
  526. private void UpdateTimeSeriesResultPanelItems()
  527. {
  528. List<Dictionary<double, LVVolumeCalcResult>> _readyShowSingleFrame = new List<Dictionary<double, LVVolumeCalcResult>>();
  529. bool hasTimeSeriesNoShow = false;
  530. if (_cardiacCurveInfos != null)
  531. {
  532. foreach (var cycleInfo in _cardiacCurveInfos.CardiacCycles)
  533. {
  534. var edesResult = new Dictionary<double, LVVolumeCalcResult>();
  535. var edInfo = cycleInfo.EDTimeStamp;
  536. var esInfo = cycleInfo.ESTimeStamp;
  537. if(cycleInfo.EDVolume == 0 || cycleInfo.ESVolume == 0)
  538. {
  539. continue;
  540. }
  541. if (!_cardiacCurveInfos.ResultPerImage.ContainsKey(cycleInfo.EDTimeStamp) ||
  542. !_cardiacCurveInfos.ResultPerImage.ContainsKey(cycleInfo.ESTimeStamp))
  543. {
  544. continue;
  545. }
  546. edesResult.Add(edInfo, _cardiacCurveInfos.ResultPerImage[cycleInfo.EDTimeStamp]);
  547. edesResult.Add(esInfo, _cardiacCurveInfos.ResultPerImage[cycleInfo.ESTimeStamp]);
  548. if(!_hasShow.ContainsKey(edInfo) && !_hasShow.ContainsKey(esInfo))
  549. {
  550. hasTimeSeriesNoShow = true;
  551. _readyShowSingleFrame.Add(edesResult);
  552. _hasShow.Add(edInfo, _cardiacCurveInfos.ResultPerImage[cycleInfo.EDTimeStamp]);
  553. _hasShow.Add(esInfo, _cardiacCurveInfos.ResultPerImage[cycleInfo.ESTimeStamp]);
  554. }
  555. }
  556. if(_readyShowSingleFrame.Count > 0 && hasTimeSeriesNoShow)
  557. {
  558. RemoveTimeSeriesResult();
  559. foreach(var timeSeries in _readyShowSingleFrame)
  560. {
  561. //取出当前图像对应的结果,得分等,生成对应的UserControl添加到Children中去
  562. string resultName = "AutoEFCalculation";
  563. Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
  564. {
  565. PanelTimeSeriesBasedResults.Children.Add(GetTextBlock(resultName + ":"));
  566. }));
  567. var keyList = timeSeries.Keys.ToList();
  568. var edVolumeName = "EDVloume";
  569. var esVolumeName = "ESVloume";
  570. var efValueName = "EFValue";
  571. var edVolume = timeSeries[keyList[0]].Volume;
  572. var esVolume = timeSeries[keyList[1]].Volume;
  573. var efValue = (edVolume - esVolume) / edVolume;
  574. Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
  575. {
  576. PanelTimeSeriesBasedResults.Children.Add(GetTextBlock(edVolumeName + ":" + edVolume.ToString("f2")));
  577. PanelTimeSeriesBasedResults.Children.Add(GetTextBlock(esVolumeName + ":" + esVolume.ToString("f2")));
  578. PanelTimeSeriesBasedResults.Children.Add(GetTextBlock(efValueName + ":" + (efValue * 100).ToString("f2") + "%"));
  579. }));
  580. var edImage = _imageInfo[keyList[0]];
  581. var esImage = _imageInfo[keyList[1]];
  582. Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
  583. {
  584. PanelTimeSeriesBasedResults.Children.Add(GetTextBlock("ED Frame" + "(" + keyList[0].ToString("f2") + "):"));
  585. PanelTimeSeriesBasedResults.Children.Add(GetTextBlock("ED ControlPoints Number:" +
  586. timeSeries[keyList[0]].MeasureMarks.ControlPoints.Length.ToString()));
  587. PanelTimeSeriesBasedResults.Children.Add(new RecognizedImages(edImage, timeSeries[keyList[0]],
  588. _enableShowObjectContour, _enableShowMeasureLine));
  589. PanelTimeSeriesBasedResults.Children.Add(GetTextBlock("ES Frame" + "(" + keyList[1].ToString("f2") + "):"));
  590. PanelTimeSeriesBasedResults.Children.Add(GetTextBlock("ES ControlPoints Number:" +
  591. timeSeries[keyList[1]].MeasureMarks.ControlPoints.Length.ToString()));
  592. PanelTimeSeriesBasedResults.Children.Add(new RecognizedImages(esImage, timeSeries[keyList[1]],
  593. _enableShowObjectContour, _enableShowMeasureLine));
  594. }));
  595. }
  596. }
  597. }
  598. //把存储的超出时间的图像和数据删掉
  599. var imageKey = _imageInfo.Keys.ToList();
  600. int imagCount = imageKey.Count;
  601. for( int i = imagCount - 1; i >= 0; i-- )
  602. {
  603. var key = imageKey[i];
  604. if( key < _cardiacCurveInfos.ResultPerImage.Keys.First())
  605. {
  606. _imageInfo.TryRemove(key, out _);
  607. }
  608. }
  609. var showKey = _hasShow.Keys.ToList();
  610. int showCount = showKey.Count;
  611. for ( int i = showCount - 1; i >= 0; i-- )
  612. {
  613. var key = showKey[i];
  614. if(key < _cardiacCurveInfos.ResultPerImage.Keys.First() )
  615. {
  616. _hasShow.Remove(key);
  617. }
  618. }
  619. }
  620. private TextBlock GetTextBlock(string text)
  621. {
  622. var textBlock = new TextBlock();
  623. textBlock.Text = text;
  624. textBlock.Margin = new Thickness(4,4,4,4);
  625. return textBlock;
  626. }
  627. #endregion
  628. }
  629. }