UCMark.xaml.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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. namespace MeterVision.Mark
  16. {
  17. /// <summary>
  18. /// UCMark.xaml 的交互逻辑
  19. /// </summary>
  20. public partial class UCMark : UserControl
  21. {
  22. //当前的放大倍率
  23. //private double _sacle_value = 1.5f;
  24. //标注的类型: 4:表盘; 3:数字域; 2:首位指针; 0:未选中
  25. private int _mark_type = 0;
  26. //是否已加载图片
  27. //private bool _loadedImage = false;
  28. private MarkManager _markManager;
  29. private int _meterType = -1;
  30. public int MeterType
  31. {
  32. private get => _meterType;
  33. set
  34. {
  35. //if(_meterType != value)
  36. {
  37. _meterType = value;
  38. SetFeatureRegion(_meterType);
  39. }
  40. }
  41. }
  42. public event Action<string,int> MeterRegion_MarkFinished;
  43. public event Action<string,int> FeatureRegion_MarkFinished;
  44. BitmapImage bitmap;
  45. public UCMark()
  46. {
  47. InitializeComponent();
  48. _mark_type = 0;
  49. _markManager = new MarkManager(drawingCanvas);
  50. _markManager.MarkError += _markManager_MarkError;
  51. _markManager.FinishMark += _markManager_FinishMark;
  52. //初始化一些控件的默认显示值
  53. txtCurPoint.Text = "";
  54. this.Loaded += UCMark_Loaded;
  55. }
  56. private void UCMark_Loaded(object sender, RoutedEventArgs e)
  57. {
  58. //throw new NotImplementedException();
  59. //ChangeScale();
  60. }
  61. private void PnlCanvas_SizeChanged(object sender, SizeChangedEventArgs e)
  62. {
  63. ChangeScale();
  64. if (_markManager != null)
  65. {
  66. _markManager.ClearMark();
  67. }
  68. }
  69. public void SetImagePath(string imgPath)
  70. {
  71. //MeterType = meterType;
  72. //加载照片
  73. LoadImage(imgPath);
  74. //设置放大倍率
  75. //_sacle_value = 1.92f;
  76. //SetScaleTrnsform(_sacle_value);
  77. }
  78. //private void SetScaleTrnsform(double scale)
  79. //{
  80. // scaleTransform.ScaleX = scale;
  81. // scaleTransform.ScaleY = scale;
  82. // _markManager.ClearMark();
  83. //}
  84. private void LoadImage(string filePath)
  85. {
  86. // 创建一个BitmapImage对象,并加载图片
  87. bitmap = new BitmapImage(new Uri(filePath));
  88. if (bitmap.Width != 320 || bitmap.Height != 240)
  89. {
  90. MessageBox.Show(Application.Current.MainWindow, "图片尺寸必须为320*240!", "提示",
  91. MessageBoxButton.OK, MessageBoxImage.Information);
  92. return;
  93. }
  94. imgControl.Source = bitmap; // 将图片显示到Image控件中
  95. drawingCanvas.Width = bitmap.PixelWidth;
  96. drawingCanvas.Height = bitmap.PixelHeight;
  97. _markManager.InitMark();
  98. }
  99. private void ChangeScale()
  100. {
  101. // 获取图片原始尺寸
  102. double imageWidth = bitmap.PixelWidth;
  103. double imageHeight = bitmap.PixelHeight;
  104. // 获取pnlCanvas的实际可用区域(考虑Margin和Padding)
  105. double containerWidth = pnlCanvas.ActualWidth - pnlCanvas.Padding.Left - pnlCanvas.Padding.Right;
  106. double containerHeight = pnlCanvas.ActualHeight - pnlCanvas.Padding.Top - pnlCanvas.Padding.Bottom;
  107. // 计算缩放比例,留5%边距
  108. double scaleX = (containerWidth * 0.95) / imageWidth;
  109. double scaleY = (containerHeight * 0.95) / imageHeight;
  110. double scale = Math.Min(scaleX, scaleY);
  111. // 应用缩放
  112. scaleTransform.ScaleX = scale;
  113. scaleTransform.ScaleY = scale;
  114. // 计算图片缩放后的尺寸
  115. double scaledWidth = imageWidth * scale;
  116. double scaledHeight = imageHeight * scale;
  117. // 将图片居中于Canvas
  118. //Canvas.SetLeft(imgControl, (containerWidth - scaledWidth) / 2);
  119. //Canvas.SetTop(imgControl, (containerHeight - scaledHeight) / 2);
  120. // 关键步骤:强制Canvas与Image的渲染区域一致
  121. drawingCanvas.Width = scaledWidth; //containerWidth; // 使Canvas宽度与Border可用区域一致
  122. drawingCanvas.Height = scaledHeight; //containerHeight; // 使Canvas高度与Border可用区域一致
  123. }
  124. private void _markManager_FinishMark(int pointCount, List<Point> points, int angle)
  125. {
  126. double scaleX = scaleTransform.ScaleX;
  127. double scaleY = scaleTransform.ScaleY;
  128. string regions = "";
  129. if (_mark_type == 4)
  130. {
  131. //表盘标注完成(获取到2组坐标)
  132. Point point1 = points[0];
  133. Point point2 = points[1];
  134. int xMin = (int)(point1.X / scaleX);
  135. int yMin = (int)(point1.Y / scaleY);
  136. int xMax = (int)(point2.X / scaleX);
  137. int yMax = (int)(point2.Y / scaleY);
  138. regions = $"{xMin},{yMin} {xMax},{yMax}";
  139. MeterRegion_MarkFinished?.Invoke(regions,MeterType);
  140. }
  141. else if (_mark_type == 3)
  142. {
  143. //数字区域标注完成
  144. regions = $"" +
  145. $"{(int)(points[0].X / scaleX)}," +
  146. $"{(int)(points[0].Y / scaleY)} " +
  147. $"{(int)(points[1].X / scaleX)}," +
  148. $"{(int)(points[1].Y / scaleY)} " +
  149. $"{(int)(points[2].X / scaleX)}," +
  150. $"{(int)(points[2].Y / scaleY)} " +
  151. $"{(int)(points[3].X / scaleX)}," +
  152. $"{(int)(points[3].Y / scaleY)}";
  153. FeatureRegion_MarkFinished?.Invoke(regions,MeterType);
  154. }
  155. else if (_mark_type == 2)
  156. {
  157. //指针首位标注完成
  158. regions = $"" +
  159. $"{(int)(points[0].X / scaleX)}," +
  160. $"{(int)(points[0].Y / scaleY)} " +
  161. $"{(int)(points[1].X / scaleX)}," +
  162. $"{(int)(points[1].Y / scaleY)}";
  163. FeatureRegion_MarkFinished?.Invoke(regions, MeterType);
  164. }
  165. }
  166. private void _markManager_MarkError(string message)
  167. {
  168. MessageBox.Show(message);
  169. }
  170. private void SetFeatureRegion(int meterType)
  171. {
  172. if(meterType == 1 || meterType == 3)
  173. {
  174. pnlMarkFunc.Visibility = Visibility.Visible;
  175. btnFeatureRegion.Visibility = txtFeatureRegion.Visibility = Visibility.Visible;
  176. btnFeatureRegion.Content = "标注数据域(4点)";
  177. }
  178. else if(meterType == 2)
  179. {
  180. pnlMarkFunc.Visibility = Visibility.Visible;
  181. btnFeatureRegion.Visibility = txtFeatureRegion.Visibility = Visibility.Visible;
  182. btnFeatureRegion.Content = "标注首位指针(2点)";
  183. }
  184. else
  185. {
  186. pnlMarkFunc.Visibility = Visibility.Hidden;
  187. //btnFeatureRegion.Visibility = txtFeatureRegion.Visibility = Visibility.Collapsed;
  188. }
  189. }
  190. private void SetBtnMark(int mark_type)
  191. {
  192. btnMeterRegion.Foreground = btnFeatureRegion.Foreground = Brushes.Black;
  193. if(mark_type == 4)
  194. {
  195. btnMeterRegion.Foreground = Brushes.Red;
  196. }
  197. else if(mark_type == 2 || mark_type == 3)
  198. {
  199. btnFeatureRegion.Foreground = Brushes.Red;
  200. }
  201. }
  202. private void BtnMeterRegion_Click(object sender, RoutedEventArgs e)
  203. {
  204. if (MeterType <= 0) return;
  205. if(_mark_type != 4)
  206. {
  207. _mark_type = 4;
  208. _markManager.ReadyMark(_mark_type);
  209. }
  210. else
  211. {
  212. _mark_type = 0;
  213. _markManager.StopMark();
  214. }
  215. SetBtnMark(_mark_type);
  216. }
  217. private void BtnFeatureRegion_Click(object sender, RoutedEventArgs e)
  218. {
  219. if(MeterType == 1 || MeterType == 3)
  220. {
  221. //数字域标注
  222. if(_mark_type != 3)
  223. {
  224. _mark_type = 3;
  225. _markManager.ReadyMark(_mark_type);
  226. }
  227. else
  228. {
  229. _mark_type = 0;
  230. _markManager.StopMark();
  231. }
  232. }
  233. else if(MeterType == 2)
  234. {
  235. //首位指针标注
  236. if(_mark_type != 2)
  237. {
  238. _mark_type = 2;
  239. _markManager.ReadyMark(_mark_type);
  240. }
  241. else
  242. {
  243. _mark_type = 2;
  244. _markManager.StopMark();
  245. }
  246. }
  247. SetBtnMark(_mark_type);
  248. }
  249. private void BtnClearMark_Click(object sender, RoutedEventArgs e)
  250. {
  251. _markManager.ClearMark();
  252. }
  253. private void DrawingCanvas_MouseDown(object sender, MouseButtonEventArgs e)
  254. {
  255. if (_markManager.IsMarking && _mark_type > 0)
  256. {
  257. //获取点击位置
  258. Point clickPoint = e.GetPosition(drawingCanvas);
  259. _markManager.PointMark(clickPoint);
  260. }
  261. }
  262. private void DrawingCanvas_MouseMove(object sender, MouseEventArgs e)
  263. {
  264. Point mousePos = e.GetPosition(drawingCanvas);
  265. // 将鼠标位置转换为原图的坐标
  266. double originalX = mousePos.X / scaleTransform.ScaleX;
  267. double originalY = mousePos.Y / scaleTransform.ScaleY;
  268. int mouseX = (int)originalX;
  269. int mouseY = (int)originalY;
  270. if(_markManager != null && _markManager.PointCount == 3) {
  271. _markManager.MouseDrawLine(mousePos);
  272. }
  273. //this.Title = $"Mouse Position : {mouseX},{mouseY}";
  274. txtCurPoint.Text = $"鼠标坐标: {mouseX},{mouseY}";
  275. }
  276. private void DrawingCanvas_MouseUp(object sender, MouseButtonEventArgs e)
  277. {
  278. }
  279. private void DrawingCanvas_MouseEnter(object sender, MouseEventArgs e)
  280. {
  281. if (_mark_type > 0)
  282. {
  283. this.Cursor = Cursors.Hand;
  284. }
  285. else
  286. {
  287. this.Cursor = Cursors.Arrow;
  288. }
  289. }
  290. private void DrawingCanvas_MouseLeave(object sender, MouseEventArgs e)
  291. {
  292. txtCurPoint.Text = "";
  293. this.Cursor = Cursors.Arrow;
  294. }
  295. //-----------------------------------------------------------------------
  296. }
  297. }