ImageCanvas.xaml.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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.Controls;
  7. using System.Windows.Threading;
  8. using System.Windows.Media.Imaging;
  9. using System.Drawing;
  10. using System.Drawing.Imaging;
  11. using YOLODetectProcessLib;
  12. namespace YOLODetectDemo
  13. {
  14. public class Roi
  15. {
  16. public Rect BoundBox { get; set; }
  17. public System.Windows.Media.Brush Color { get; set; }
  18. public string LabelName { get; set; }
  19. }
  20. public class MyTransform
  21. {
  22. public double Scale { get; set; }
  23. public double OffsetX { get; set; }
  24. public double OffsetY { get; set; }
  25. public MyTransform(double scale, double offsetX, double offsetY)
  26. {
  27. Scale = scale;
  28. OffsetX = offsetX;
  29. OffsetY = offsetY;
  30. }
  31. public System.Windows.Point Transform(System.Windows.Point point)
  32. {
  33. double x = OffsetX + Scale * point.X;
  34. double y = OffsetY + Scale * point.Y;
  35. return new System.Windows.Point(x, y);
  36. }
  37. public System.Windows.Rect Transform(System.Windows.Rect rect)
  38. {
  39. double left = OffsetX + Scale * rect.Left;
  40. double top = OffsetY + Scale * rect.Top;
  41. double width = Scale * rect.Width;
  42. double height = Scale * rect.Height;
  43. return new System.Windows.Rect(left, top, width, height);
  44. }
  45. }
  46. /// <summary>
  47. /// ImageCanvas.xaml 的交互逻辑
  48. /// </summary>
  49. public partial class ImageCanvas : UserControl
  50. {
  51. #region private
  52. private Bitmap _image;
  53. private List<Roi> _rois;
  54. private volatile bool _enableAI;
  55. private volatile bool _showContour;
  56. private volatile bool _showSize;
  57. private MyTransform _transform;
  58. #endregion
  59. #region properties
  60. public Bitmap Image { get => _image; }
  61. #endregion
  62. #region 用户界面响应
  63. private void CanvasSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
  64. {
  65. UpdateTransforms();
  66. }
  67. #endregion
  68. #region public
  69. public ImageCanvas()
  70. {
  71. InitializeComponent();
  72. }
  73. public void SetShowParams(bool enableAI)
  74. {
  75. _enableAI = enableAI;
  76. if (_rois != null)
  77. {
  78. for (int ni = 0; ni < _rois.Count; ni++)
  79. {
  80. DrawRoiInCanvas(_rois[ni], ni.ToString());
  81. }
  82. }
  83. }
  84. public void UpdateImage(Bitmap image)
  85. {
  86. _image = image.Clone(new Rectangle(0, 0, image.Width, image.Height), image.PixelFormat);
  87. // 更新缩放比例
  88. UpdateTransforms();
  89. // 更新图像显示
  90. var bitmapImage = BitmapToBitmapImage(image);
  91. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
  92. {
  93. ImageShow.Source = bitmapImage;
  94. }));
  95. }
  96. #endregion
  97. #region private
  98. private void RemoveRoiInCanvas(string roiName)
  99. {
  100. // 文字
  101. string textName = "Text_" + roiName;
  102. System.Windows.Controls.TextBlock textExist = RoiCanvas.FindName(textName) as System.Windows.Controls.TextBlock;
  103. if (textExist != null)
  104. {
  105. RoiCanvas.Children.Remove(textExist);
  106. RoiCanvas.UnregisterName(textName);
  107. }
  108. }
  109. private void DrawRoiInCanvas(Roi roi, string roiName)
  110. {
  111. if (_transform == null)
  112. {
  113. return;
  114. }
  115. // 已有则删除
  116. RemoveRoiInCanvas(roiName);
  117. // 不启用AI,则直接退出
  118. if (!_enableAI)
  119. {
  120. return;
  121. }
  122. // 将Roi的序号写在左上角
  123. var pointLT = new System.Windows.Point(roi.BoundBox.Left, roi.BoundBox.Top);
  124. var transPointLT = _transform.Transform(pointLT);
  125. var textLeft = transPointLT.X - 16;
  126. var textTop = transPointLT.Y;
  127. TextBlock text = new TextBlock();
  128. text.Text = roiName;
  129. text.FontSize = 16;
  130. text.FontWeight = System.Windows.FontWeights.Bold;
  131. text.Foreground = roi.Color;
  132. text.VerticalAlignment = System.Windows.VerticalAlignment.Top;
  133. Canvas.SetLeft(text, textLeft);
  134. Canvas.SetTop(text, textTop);
  135. RoiCanvas.Children.Add(text);
  136. string textName = "Text_" + roiName;
  137. RoiCanvas.RegisterName(textName, text);
  138. }
  139. private BitmapImage BitmapToBitmapImage(Bitmap img)
  140. {
  141. BitmapImage bmpimg = new BitmapImage();
  142. using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
  143. {
  144. img.Save(ms, ImageFormat.Png);
  145. bmpimg.BeginInit();
  146. bmpimg.StreamSource = ms;
  147. bmpimg.CacheOption = BitmapCacheOption.OnLoad;
  148. bmpimg.EndInit();
  149. bmpimg.Freeze();
  150. ms.Dispose();
  151. }
  152. return bmpimg;
  153. }
  154. private void UpdateTransforms()
  155. {
  156. if (_image != null)
  157. {
  158. // 使图片保持长宽比例,居中显示,需要平移和缩放
  159. var imgWidth = _image.Width;
  160. var imgHeight = _image.Height;
  161. var canvasWidth = RoiCanvas.ActualWidth;
  162. var canvasHeight = RoiCanvas.ActualHeight;
  163. var scaleX = canvasWidth / imgWidth;
  164. var scaleY = canvasHeight / imgHeight;
  165. var scale = scaleX < scaleY ? scaleX : scaleY;
  166. double offsetX, offsetY;
  167. if (Math.Abs(scale - scaleX) < 0.0001)
  168. {
  169. offsetY = 0.5 * (scaleY - scale) * imgHeight;
  170. offsetX = 0;
  171. }
  172. else
  173. {
  174. offsetX = 0.5 * (scaleX - scale) * imgWidth;
  175. offsetY = 0;
  176. }
  177. _transform = new MyTransform(scale, offsetX, offsetY);
  178. }
  179. }
  180. #endregion
  181. }
  182. }