1
0

ImageCanvas.xaml.cs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. using AI.Common;
  2. using UsHepatoRenalRatioDetectLib;
  3. using UsHepatoRenalRatioDetectLib.OrganSegProcessModule;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Drawing;
  7. using System.Drawing.Imaging;
  8. using System.Windows;
  9. using System.Windows.Controls;
  10. using System.Windows.Media;
  11. using System.Windows.Media.Imaging;
  12. using System.Windows.Threading;
  13. using static System.Net.Mime.MediaTypeNames;
  14. using Rect = AI.Common.Rect;
  15. namespace HepatoRenalEchoContrastDemo
  16. {
  17. //public class TestResults
  18. //{
  19. // public Point2D[][] Countours { get; set; }
  20. // public Rect[] Rois { get; set; }
  21. // public double EchoContastValue { get; set; }
  22. // public TestResults(Point2D[][] countours, Rect[] rois, double echoContastValue)
  23. // {
  24. // Countours = countours;
  25. // Rois = rois;
  26. // EchoContastValue = echoContastValue;
  27. // }
  28. //}
  29. public class RoiInfo
  30. {
  31. public Rect RoiRect { get; set; }
  32. public System.Windows.Media.Brush Color { get; set; }
  33. public RoiInfo(Rect roi, System.Windows.Media.Brush color)
  34. {
  35. RoiRect = roi;
  36. Color = color;
  37. }
  38. }
  39. public class OrganInfo
  40. {
  41. public string OrganName { get; set; }
  42. public Rect BoundingBox { get; set; }
  43. public Point2D[][] Contours { get; set; }
  44. public System.Windows.Media.Brush Color => System.Windows.Media.Brushes.Green;
  45. public OrganInfo(string organName, Rect boundingBox, Point2D[][] contours)
  46. {
  47. OrganName = organName;
  48. BoundingBox = boundingBox;
  49. Contours = contours;
  50. }
  51. }
  52. public class MyTransform
  53. {
  54. public double Scale { get; set; }
  55. public double OffsetX { get; set; }
  56. public double OffsetY { get; set; }
  57. public MyTransform(double scale, double offsetX, double offsetY)
  58. {
  59. Scale = scale;
  60. OffsetX = offsetX;
  61. OffsetY = offsetY;
  62. }
  63. public System.Windows.Point Transform(System.Windows.Point point)
  64. {
  65. double x = OffsetX + Scale * point.X;
  66. double y = OffsetY + Scale * point.Y;
  67. return new System.Windows.Point(x, y);
  68. }
  69. public System.Windows.Rect Transform(System.Windows.Rect rect)
  70. {
  71. double left = OffsetX + Scale * rect.Left;
  72. double top = OffsetY + Scale * rect.Top;
  73. double width = Scale * rect.Width;
  74. double height = Scale * rect.Height;
  75. return new System.Windows.Rect(left, top, width, height);
  76. }
  77. }
  78. /// <summary>
  79. /// ImageCanvas.xaml 的交互逻辑
  80. /// </summary>
  81. public partial class ImageCanvas : UserControl
  82. {
  83. #region private variables
  84. private Bitmap _image;
  85. private List<RoiInfo> _rois;
  86. private List<OrganInfo> _organs;
  87. private volatile bool _showOrgan;
  88. private volatile bool _showRois;
  89. private volatile bool _showEchoContastValue;
  90. private MyTransform _transform;
  91. private double _echoContrastRatio;
  92. #endregion
  93. #region 用户界面响应
  94. private void CanvasSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
  95. {
  96. UpdateTransforms();
  97. }
  98. #endregion
  99. #region public funcs
  100. public ImageCanvas()
  101. {
  102. InitializeComponent();
  103. }
  104. /// <summary>
  105. /// 设置显示参数
  106. /// </summary>
  107. /// <param name="showCountours"></param>
  108. /// <param name="showRois"></param>
  109. /// <param name="showeEchoContastValue"></param>
  110. public void SetShowParams(bool showCountours, bool showRois, bool showeEchoContastValue)
  111. {
  112. _showOrgan = showCountours;
  113. _showRois = showRois;
  114. _showEchoContastValue = showeEchoContastValue;
  115. if (_rois != null)
  116. {
  117. UpdateRois();
  118. }
  119. if (_organs != null)
  120. {
  121. UpdateOrgans();
  122. }
  123. }
  124. public void UpdateImage(Bitmap image)
  125. {
  126. if (_image != null)
  127. {
  128. _image.Dispose();
  129. }
  130. _image = image.Clone(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), image.PixelFormat);
  131. // 更新缩放比例
  132. UpdateTransforms();
  133. // 更新图像显示
  134. var bitmapImage = BitmapToBitmapImage(image);
  135. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
  136. {
  137. ImageShow.Source = bitmapImage;
  138. }));
  139. }
  140. public void UpdateTestResults(HRRDetectResultPerImg detectedResult)
  141. {
  142. List<OrganInfo> organs = new List<OrganInfo>();
  143. List<RoiInfo> rois = new List<RoiInfo>();
  144. foreach (var organ in detectedResult.SegResults)
  145. {
  146. organs.Add(new OrganInfo(organ.Organ.ToString(), organ.BoundingBox, organ.Contours));
  147. }
  148. foreach (var roiDict in detectedResult.Rois)
  149. {
  150. rois.Add(new RoiInfo(roiDict.Value, System.Windows.Media.Brushes.Yellow));
  151. }
  152. // 删掉旧的Roi和Organ
  153. RemoveRois();
  154. RemoveOrgans();
  155. RemoveText();
  156. _organs = organs;
  157. _rois = rois;
  158. _echoContrastRatio = detectedResult.HepatoRenalRatio;
  159. // 更新画布上显示的Roi和Organ
  160. ////////////////////////////////
  161. double ratio = Math.Round(_echoContrastRatio, 4);
  162. if (ratio > 0)
  163. {
  164. UpdateRois();
  165. }
  166. ///////////////////////////////
  167. UpdateOrgans();
  168. UpdateText();
  169. }
  170. public void ClearTestResult()
  171. {
  172. // 删掉旧的Roi和Organ
  173. RemoveRois();
  174. RemoveOrgans();
  175. RemoveText();
  176. // 设置
  177. _rois = null;
  178. _organs = null;
  179. }
  180. /// <summary>
  181. /// 将画布上的点转到图像坐标系下
  182. /// </summary>
  183. /// <param name="point"></param>
  184. /// <returns></returns>
  185. public Point2D TransBack(System.Windows.Point point)
  186. {
  187. int x = Convert.ToInt32((point.X - _transform.OffsetX) / _transform.Scale);
  188. int y = Convert.ToInt32((point.Y - _transform.OffsetY) / _transform.Scale);
  189. return new Point2D(x, y);
  190. }
  191. #endregion
  192. #region private funcs
  193. private BitmapImage BitmapToBitmapImage(Bitmap img)
  194. {
  195. BitmapImage bmpimg = new BitmapImage();
  196. using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
  197. {
  198. img.Save(ms, ImageFormat.Png);
  199. bmpimg.BeginInit();
  200. bmpimg.StreamSource = ms;
  201. bmpimg.CacheOption = BitmapCacheOption.OnLoad;
  202. bmpimg.EndInit();
  203. bmpimg.Freeze();
  204. ms.Dispose();
  205. }
  206. return bmpimg;
  207. }
  208. public void RemoveRoiInCanvas(string roiName)
  209. {
  210. // 框
  211. string rectName = "ROI_Rect_" + roiName;
  212. System.Windows.Shapes.Rectangle rectExist = TestResultCanvas.FindName(rectName) as System.Windows.Shapes.Rectangle;
  213. if (rectExist != null)
  214. {
  215. TestResultCanvas.Children.Remove(rectExist);
  216. TestResultCanvas.UnregisterName(rectName);
  217. }
  218. // 文字
  219. string textName = "ROI_Text_" + roiName;
  220. System.Windows.Controls.TextBlock textExist = TestResultCanvas.FindName(textName) as System.Windows.Controls.TextBlock;
  221. if (textExist != null)
  222. {
  223. TestResultCanvas.Children.Remove(textExist);
  224. TestResultCanvas.UnregisterName(textName);
  225. }
  226. }
  227. private void RemoveOrganInCanvas(OrganInfo organ)
  228. {
  229. string organName = organ.OrganName;
  230. // 框
  231. string rectName = "Organ_Rect_" + organName;
  232. System.Windows.Shapes.Rectangle rectExist = TestResultCanvas.FindName(rectName) as System.Windows.Shapes.Rectangle;
  233. if (rectExist != null)
  234. {
  235. TestResultCanvas.Children.Remove(rectExist);
  236. TestResultCanvas.UnregisterName(rectName);
  237. }
  238. // 轮廓
  239. int count = organ.Contours.Length;
  240. for (int ni = 0; ni < count; ni++)
  241. {
  242. string contourName = "Organ_Contour_" + organName + "_" + ni;
  243. System.Windows.Shapes.Polygon contourExist = TestResultCanvas.FindName(contourName) as System.Windows.Shapes.Polygon;
  244. if (contourExist != null)
  245. {
  246. TestResultCanvas.Children.Remove(contourExist);
  247. TestResultCanvas.UnregisterName(contourName);
  248. }
  249. }
  250. // 文字
  251. string textName = "Organ_Text_" + organName;
  252. System.Windows.Controls.TextBlock textExist = TestResultCanvas.FindName(textName) as System.Windows.Controls.TextBlock;
  253. if (textExist != null)
  254. {
  255. TestResultCanvas.Children.Remove(textExist);
  256. TestResultCanvas.UnregisterName(textName);
  257. }
  258. }
  259. public void DrawRoiInCanvas(RoiInfo roi, string roiName)
  260. {
  261. if (_transform == null)
  262. {
  263. return;
  264. }
  265. // 已有则删除
  266. RemoveRoiInCanvas(roiName);
  267. // 不显示ROI,则直接退出
  268. if (!_showRois)
  269. {
  270. return;
  271. }
  272. // 画框
  273. var rect = new System.Windows.Rect(roi.RoiRect.Left, roi.RoiRect.Top, roi.RoiRect.Width, roi.RoiRect.Height);
  274. var transRect = _transform.Transform(rect);
  275. System.Windows.Shapes.Rectangle rectDraw = new System.Windows.Shapes.Rectangle();
  276. rectDraw.StrokeThickness = 3;
  277. rectDraw.Stroke = roi.Color;
  278. rectDraw.Width = transRect.Width;
  279. rectDraw.Height = transRect.Height;
  280. Canvas.SetLeft(rectDraw, transRect.Left);
  281. Canvas.SetTop(rectDraw, transRect.Top);
  282. TestResultCanvas.Children.Add(rectDraw);
  283. string rectName = "ROI_Rect_" + roiName;
  284. TestResultCanvas.RegisterName(rectName, rectDraw);
  285. // 将Roi的序号写在左上角
  286. var pointLT = new System.Windows.Point(roi.RoiRect.Left, roi.RoiRect.Top);
  287. var transPointLT = _transform.Transform(pointLT);
  288. var textLeft = transPointLT.X - 16;
  289. var textTop = transPointLT.Y;
  290. TextBlock text = new TextBlock();
  291. text.Text = roiName;
  292. text.FontSize = 16;
  293. text.FontWeight = System.Windows.FontWeights.Bold;
  294. text.Foreground = roi.Color;
  295. text.VerticalAlignment = System.Windows.VerticalAlignment.Top;
  296. Canvas.SetLeft(text, textLeft);
  297. Canvas.SetTop(text, textTop);
  298. TestResultCanvas.Children.Add(text);
  299. string textName = "ROI_Text_" + roiName;
  300. TestResultCanvas.RegisterName(textName, text);
  301. }
  302. private void DrawOrganInCanvas(OrganInfo organ)
  303. {
  304. if (_transform == null)
  305. {
  306. return;
  307. }
  308. // 已有则删除
  309. RemoveOrganInCanvas(organ);
  310. // 是否显示Organ
  311. if (!_showOrgan)
  312. {
  313. return;
  314. }
  315. // 有轮廓就显示轮廓,没有轮廓就显示方框
  316. string organName = organ.OrganName;
  317. if (organ.Contours.Length > 0)
  318. {
  319. int count = organ.Contours.Length;
  320. for (int ni = 0; ni < count; ni++)
  321. {
  322. Point2D[] contour = organ.Contours[ni];
  323. PointCollection contourPoints = new PointCollection();
  324. for (int nj = 0; nj < contour.Length; nj++)
  325. {
  326. var point = new System.Windows.Point(contour[nj].X, contour[nj].Y);
  327. var transPoint = _transform.Transform(point);
  328. contourPoints.Add(transPoint);
  329. }
  330. System.Windows.Shapes.Polygon contourDraw = new System.Windows.Shapes.Polygon();
  331. contourDraw.Points = contourPoints;
  332. contourDraw.StrokeThickness = 3;
  333. contourDraw.Stroke = organ.Color;
  334. TestResultCanvas.Children.Add(contourDraw);
  335. string contourName = "Organ_Contour_" + organName + "_" + ni;
  336. TestResultCanvas.RegisterName(contourName, contourDraw);
  337. }
  338. }
  339. else
  340. {
  341. var rect = new System.Windows.Rect(organ.BoundingBox.Left, organ.BoundingBox.Top, organ.BoundingBox.Width, organ.BoundingBox.Height);
  342. var transRect = _transform.Transform(rect);
  343. System.Windows.Shapes.Rectangle rectDraw = new System.Windows.Shapes.Rectangle();
  344. rectDraw.StrokeThickness = 3;
  345. rectDraw.Stroke = organ.Color;
  346. rectDraw.Width = transRect.Width;
  347. rectDraw.Height = transRect.Height;
  348. Canvas.SetLeft(rectDraw, transRect.Left);
  349. Canvas.SetTop(rectDraw, transRect.Top);
  350. TestResultCanvas.Children.Add(rectDraw);
  351. string rectName = "Organ_Rect_" + organName;
  352. TestResultCanvas.RegisterName(rectName, rectDraw);
  353. }
  354. // 将Organ的序号写在左上角
  355. var pointLT = new System.Windows.Point(organ.BoundingBox.Left, organ.BoundingBox.Top);
  356. var transPointLT = _transform.Transform(pointLT);
  357. var textLeft = transPointLT.X + 16;
  358. var textTop = transPointLT.Y;
  359. TextBlock text = new TextBlock();
  360. text.Text = organName;
  361. text.FontSize = 16;
  362. text.FontWeight = System.Windows.FontWeights.Bold;
  363. text.Foreground = organ.Color;
  364. text.VerticalAlignment = System.Windows.VerticalAlignment.Top;
  365. Canvas.SetLeft(text, textLeft);
  366. Canvas.SetTop(text, textTop);
  367. TestResultCanvas.Children.Add(text);
  368. string textName = "Organ_Text_" + organName;
  369. TestResultCanvas.RegisterName(textName, text);
  370. }
  371. private void UpdateTransforms()
  372. {
  373. if (_image != null)
  374. {
  375. // 使图片保持长宽比例,居中显示,需要平移和缩放
  376. var imgWidth = _image.Width;
  377. var imgHeight = _image.Height;
  378. var canvasWidth = TestResultCanvas.ActualWidth;
  379. var canvasHeight = TestResultCanvas.ActualHeight;
  380. var scaleX = canvasWidth / imgWidth;
  381. var scaleY = canvasHeight / imgHeight;
  382. var scale = scaleX < scaleY ? scaleX : scaleY;
  383. double offsetX, offsetY;
  384. if (Math.Abs(scale - scaleX) < 0.0001)
  385. {
  386. offsetY = 0.5 * (scaleY - scale) * imgHeight;
  387. offsetX = 0;
  388. }
  389. else
  390. {
  391. offsetX = 0.5 * (scaleX - scale) * imgWidth;
  392. offsetY = 0;
  393. }
  394. _transform = new MyTransform(scale, offsetX, offsetY);
  395. }
  396. }
  397. private void RemoveRois()
  398. {
  399. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  400. {
  401. // 移除所有旧的ROI
  402. if (_rois != null)
  403. {
  404. for (int ni = 0; ni < _rois.Count; ni++)
  405. {
  406. RemoveRoiInCanvas(ni.ToString());
  407. }
  408. }
  409. }));
  410. }
  411. private void RemoveOrgans()
  412. {
  413. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  414. {
  415. // 移除所有旧的Organ
  416. if (_organs != null)
  417. {
  418. for (int ni = 0; ni < _organs.Count; ni++)
  419. {
  420. RemoveOrganInCanvas(_organs[ni]);
  421. }
  422. }
  423. }));
  424. }
  425. private void RemoveText()
  426. {
  427. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  428. {
  429. // 文字
  430. string textName = "Ratio";
  431. System.Windows.Controls.TextBlock textExist = TestResultCanvas.FindName(textName) as System.Windows.Controls.TextBlock;
  432. if (textExist != null)
  433. {
  434. TestResultCanvas.Children.Remove(textExist);
  435. TestResultCanvas.UnregisterName(textName);
  436. }
  437. }));
  438. }
  439. private void UpdateRois()
  440. {
  441. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  442. {
  443. if (_rois != null)
  444. {
  445. for (int ni = 0; ni < _rois.Count; ni++)
  446. {
  447. DrawRoiInCanvas(_rois[ni], ni.ToString());
  448. }
  449. }
  450. }));
  451. }
  452. private void UpdateOrgans()
  453. {
  454. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  455. {
  456. if (_organs != null)
  457. {
  458. for (int ni = 0; ni < _organs.Count; ni++)
  459. {
  460. DrawOrganInCanvas(_organs[ni]);
  461. }
  462. }
  463. }));
  464. }
  465. private void UpdateText()
  466. {
  467. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  468. {
  469. if (_transform == null)
  470. {
  471. return;
  472. }
  473. // 已有则删除
  474. RemoveText();
  475. // 不显示ROI,则直接退出
  476. if (!_showRois)
  477. {
  478. return;
  479. }
  480. var pointLT = new System.Windows.Point(50, 50);
  481. var transPointLT = _transform.Transform(pointLT);
  482. var textLeft = transPointLT.X - 16;
  483. var textTop = transPointLT.Y;
  484. TextBlock text = new TextBlock();
  485. double ratio = Math.Round(_echoContrastRatio, 4);
  486. text.Text = ratio.ToString();
  487. if (ratio<=0)
  488. {
  489. text.Text = "Invalid !";
  490. }
  491. text.FontSize = 30;
  492. text.FontWeight = System.Windows.FontWeights.Bold;
  493. text.Foreground = System.Windows.Media.Brushes.Yellow;
  494. text.VerticalAlignment = System.Windows.VerticalAlignment.Top;
  495. Canvas.SetLeft(text, textLeft);
  496. Canvas.SetTop(text, textTop);
  497. TestResultCanvas.Children.Add(text);
  498. string textName = "Ratio";
  499. TestResultCanvas.RegisterName(textName, text);
  500. }));
  501. }
  502. #endregion
  503. }
  504. }