MainWindow.xaml.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. using AI.Common.Interface;
  2. using AICustomizeSDKDemo.Infrastucture;
  3. using AICustomizeSDKDemo.Presentation;
  4. using AICustomizeSDKDemo.Service;
  5. using AICustomizeSDKDemo.Settings;
  6. using CustomizeDiagnosisSDK;
  7. using CustomizeDiagnosisSDK.Interfaces;
  8. using System;
  9. using System.Collections.Generic;
  10. using System.Diagnostics;
  11. using System.Drawing;
  12. using System.Linq;
  13. using System.Threading;
  14. using System.Windows;
  15. using System.Windows.Controls;
  16. using System.Windows.Input;
  17. using System.Windows.Threading;
  18. using Path = System.IO.Path;
  19. using Point = System.Windows.Point;
  20. namespace AICustomizeSDKDemo
  21. {
  22. /// <summary>
  23. /// MainWindow.xaml 的交互逻辑
  24. /// </summary>
  25. public partial class MainWindow : Window
  26. {
  27. private CustomizeDiagnosisSDK.CustomizeDiagnosis _customizeDiagnosis;
  28. private string _calcultaionId;
  29. private bool _isPlaying;
  30. private Bitmap _image;
  31. private List<Organ> _organs;
  32. private MyTransform _transform;
  33. private IPlayer _player;
  34. private IImageProvider _customizeDiagnosisImageProvider;
  35. private IDetectedObject[] _currentDetectedObject;
  36. private Stopwatch _stopwatch;
  37. private int _startTickCount;
  38. private SettingWindow _settingWindow;
  39. public MainWindow()
  40. {
  41. InitializeComponent();
  42. try
  43. {
  44. _stopwatch = new Stopwatch();
  45. Logger.Info("The Customer Diagnosis System SDK Demo Program started.");
  46. var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CustomizeDiagnosisSystem");
  47. MaxButton.Visibility = Visibility.Collapsed;
  48. RestoreButton.Visibility = Visibility.Visible;
  49. OnValueChanged(null, new List<SettingProperty>
  50. {
  51. SettingProperty.IsEnableAI,
  52. });
  53. InitializePlayer();
  54. OnPlayerChanged(null, EventArgs.Empty);
  55. PlayerManager.Instance.PlayerChanged += OnPlayerChanged;
  56. SettingConfig.Instance.ValueChangedEvent += OnValueChanged;
  57. }
  58. catch (Exception ex)
  59. {
  60. Logger.Error($"MainWindow :{ex}");
  61. }
  62. }
  63. private void RemoveOldCache()
  64. {
  65. RemoveOrgans();
  66. _organs = null;
  67. _currentDetectedObject = null;
  68. }
  69. private void InitializePlayer()
  70. {
  71. if (_player != null)
  72. {
  73. _player.Stop();
  74. _player.InputFrameReceived -= OnInputFrameReceived;
  75. _player.FPSChanged -= OnFPSChanged;
  76. }
  77. _player = PlayerManager.Instance.Player;
  78. if (_player != null)
  79. {
  80. _player.InputFrameReceived += OnInputFrameReceived;
  81. _player.FPSChanged += OnFPSChanged;
  82. _player.Play();
  83. _isPlaying = true;
  84. Dispatcher.Invoke(() =>
  85. {
  86. PlayButton.IsEnabled = SettingConfig.Instance.IsVideo;
  87. if (PlayButton.Visibility == Visibility.Visible)
  88. {
  89. PlayButton.Visibility = Visibility.Collapsed;
  90. }
  91. });
  92. }
  93. }
  94. private void OnPlayerChanged(object sender, EventArgs e)
  95. {
  96. if (_player != null)
  97. {
  98. _player.InputFrameReceived -= OnInputFrameReceived;
  99. _player.FPSChanged -= OnFPSChanged;
  100. _player.Stop();
  101. }
  102. _player = PlayerManager.Instance.Player;
  103. Logger.Info($"Player Changed:{SettingConfig.Instance.UltrasoundImageSource}");
  104. if (_player != null)
  105. {
  106. _player.InputFrameReceived += OnInputFrameReceived;
  107. _player.FPSChanged += OnFPSChanged;
  108. _player.Play();
  109. Dispatcher.Invoke(() =>
  110. {
  111. VideoProgress.Maximum = _player.TotalFrameCount - 1;
  112. });
  113. _isPlaying = true;
  114. Dispatcher.Invoke(() =>
  115. {
  116. PlayButton.IsEnabled = SettingConfig.Instance.IsVideo;
  117. if (PlayButton.Visibility == Visibility.Visible)
  118. {
  119. PlayButton.Visibility = Visibility.Collapsed;
  120. }
  121. });
  122. if (SettingConfig.Instance.IsEnableAI)
  123. {
  124. if (SettingConfig.Instance.IsVideo == false)//当源文件为图片的情况下,就重新Show一次给AI提供图片信息。
  125. {
  126. DetectImage();
  127. }
  128. }
  129. }
  130. }
  131. private void DetectImage()
  132. {
  133. if (_image != null)
  134. {
  135. if (_customizeDiagnosis != null)
  136. {
  137. using (var rawImage = BitmapHelper.BitmapToRawImage(_image, true))
  138. {
  139. var imageDataId = new ImageDataId
  140. {
  141. DataName = Guid.NewGuid().ToString(),
  142. CaseId = Guid.NewGuid().ToString(),
  143. IsVideo = true,
  144. FrameTimeStamp = 0,
  145. };
  146. var input = new ImageInputData(rawImage, imageDataId);
  147. if (SettingConfig.Instance.IsAsync)
  148. {
  149. OnStartEvaluationNotification(this, EventArgs.Empty);
  150. _customizeDiagnosis.DetectOneImageAsync(input);
  151. }
  152. else
  153. {
  154. OnStartEvaluationNotification(this, EventArgs.Empty);
  155. var result = _customizeDiagnosis.DetectOneImage(input);
  156. OnAIFinishEvaluationNotification(this, result);
  157. }
  158. }
  159. }
  160. }
  161. }
  162. private void StartDiagnosis()
  163. {
  164. try
  165. {
  166. switch (SettingConfig.Instance.AIDiagnosisType)
  167. {
  168. case AIDiagnosisType.CustomizeDiagnosis:
  169. if (_customizeDiagnosis == null)
  170. {
  171. if (_customizeDiagnosisImageProvider == null)
  172. {
  173. _customizeDiagnosisImageProvider = new ImageProvider();
  174. }
  175. _customizeDiagnosis = new CustomizeDiagnosis();
  176. Logger.Info("Initialize Diagnosis");
  177. }
  178. if (_customizeDiagnosis != null)
  179. {
  180. _customizeDiagnosis.Initialize(null, _customizeDiagnosisImageProvider, SettingConfig.Instance.DetectMode, SettingConfig.Instance.DetectTps, SettingConfig.Instance.IntervalTime);
  181. _customizeDiagnosis.StartEvaluation += OnStartEvaluationNotification;
  182. _customizeDiagnosis.FinishEvaluation += OnAIFinishEvaluationNotification;
  183. _customizeDiagnosis.Start();
  184. Logger.Info("Start Diagnosis");
  185. }
  186. break;
  187. }
  188. }
  189. catch (Exception ex)
  190. {
  191. MessageBox.Show($"Start Diagnosis Error:{ex}");
  192. }
  193. }
  194. private void StopDiagnosis()
  195. {
  196. if (_customizeDiagnosis != null)
  197. {
  198. _customizeDiagnosis.StartEvaluation -= OnStartEvaluationNotification;
  199. _customizeDiagnosis.FinishEvaluation -= OnAIFinishEvaluationNotification;
  200. _customizeDiagnosis.Stop();
  201. _customizeDiagnosis = null;
  202. Logger.Info("Stop Diagnosis");
  203. }
  204. }
  205. private void CloseDiagnosis()
  206. {
  207. if (_customizeDiagnosis != null)
  208. {
  209. _customizeDiagnosis.StartEvaluation -= OnStartEvaluationNotification;
  210. _customizeDiagnosis.FinishEvaluation -= OnAIFinishEvaluationNotification;
  211. _customizeDiagnosis.Close();
  212. _customizeDiagnosis = null;
  213. Logger.Info("Close Diagnosis");
  214. }
  215. }
  216. private void OnStartEvaluationNotification(object sender, EventArgs e)
  217. {
  218. _stopwatch.Restart();
  219. Logger.Info($"Start AI Detection");
  220. Dispatcher.Invoke(() =>
  221. {
  222. ErrorInfoText.Text = null;
  223. });
  224. }
  225. #region OnAIFinishEvaluationNotification
  226. private void OnAIFinishEvaluationNotification(object sender, IDetectedObject[] diagResult)
  227. {
  228. try
  229. {
  230. if (diagResult != null && diagResult.Length > 0)
  231. {
  232. Logger.Info("Finish AI Detection");
  233. _stopwatch.Stop();
  234. var elapsedTime = _stopwatch.ElapsedMilliseconds;
  235. var dateTimeNow = DateTime.Now;
  236. // 整理诊断结果中相关信息
  237. List<Organ> organs = new List<Organ>();
  238. UpdateTransforms();
  239. Logger.Info("Update Transforms");
  240. if (diagResult == null)
  241. {
  242. return;
  243. }
  244. foreach (var result in diagResult)
  245. {
  246. organs.Add(new Organ(result.Label.Name, (AI.Common.Interface.Rect)result.BoundingBox));
  247. }
  248. // 删掉旧的Roi和Organ
  249. RemoveOldCache();
  250. // 设置
  251. _organs = organs;
  252. // 更新画布上显示的Organ
  253. UpdateOrgans();
  254. Logger.Info("Update Organs");
  255. var score = diagResult.FirstOrDefault().Score;
  256. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  257. {
  258. ResultInfoText.Text = $"Score:{score},时间:{dateTimeNow:yyyyMMddHHmmss}_{dateTimeNow.Millisecond:d3}";
  259. ElapsedTimeText.Text = $"AI耗时: {elapsedTime}ms";
  260. }));
  261. }
  262. else
  263. {
  264. Logger.Info("diag Result is null!");
  265. }
  266. }
  267. catch
  268. {
  269. }
  270. }
  271. #endregion OnAIFinishEvaluationNotification
  272. private void OnInputFrameReceived(object sender, Bitmap e)
  273. {
  274. _image = e.Clone(new System.Drawing.Rectangle(0, 0, e.Width, e.Height), e.PixelFormat);
  275. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  276. {
  277. var bitmapimage = BitmapHelper.BitmapToBitmapImage(e);
  278. UsImage.Source = bitmapimage;
  279. }));
  280. var player = sender as IPlayer;
  281. if (player != null)
  282. {
  283. Dispatcher.Invoke(() =>
  284. {
  285. VideoProgress.Value = player.FrameIndex;
  286. });
  287. }
  288. }
  289. private void OnFPSChanged(object sender, int fps)
  290. {
  291. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  292. {
  293. if (fps > 0)
  294. {
  295. FPSText.Text = $"实际帧率:{fps} fps";
  296. }
  297. else
  298. {
  299. FPSText.Text = "";
  300. }
  301. }));
  302. }
  303. private void OnValueChanged(object sender, List<SettingProperty> e)
  304. {
  305. //当AI功能变更
  306. if (e.Contains(SettingProperty.IsEnableAI) || e.Contains(SettingProperty.AIDiagnosisType))
  307. {
  308. if (e.Contains(SettingProperty.AIDiagnosisType))
  309. {
  310. _player?.Stop();
  311. }
  312. Logger.Info($"Enable AI:\"{SettingConfig.Instance.IsEnableAI}\",Detect Mode:\"{SettingConfig.Instance.DetectMode}\",Detect Tps:\"{SettingConfig.Instance.DetectTps}\",Interval Time:\"{SettingConfig.Instance.IntervalTime}\"");
  313. CloseDiagnosis();
  314. CleanAIResult();
  315. if (e.Contains(SettingProperty.AIDiagnosisType))
  316. {
  317. _player?.Play();
  318. }
  319. if (SettingConfig.Instance.IsEnableAI)
  320. {
  321. StartDiagnosis();
  322. if (SettingConfig.Instance.IsVideo == false)//当源文件为图片的情况下,就重新Show一次给AI提供图片信息。
  323. {
  324. DetectImage();
  325. }
  326. }
  327. }
  328. else
  329. {
  330. if (SettingConfig.Instance.IsEnableAI)
  331. {
  332. if (e.Contains(SettingProperty.DetectTps))
  333. {
  334. Logger.Info($"Detect Tps:\"{SettingConfig.Instance.DetectTps}\"");
  335. if (_customizeDiagnosis != null)
  336. {
  337. _customizeDiagnosis.DetectTps = SettingConfig.Instance.DetectTps;
  338. }
  339. }
  340. if (e.Contains(SettingProperty.IntervalTime))
  341. {
  342. Logger.Info($"Interval Time:\"{SettingConfig.Instance.IntervalTime}\"");
  343. if (_customizeDiagnosis != null)
  344. {
  345. _customizeDiagnosis.IntervalTime = SettingConfig.Instance.IntervalTime;
  346. }
  347. }
  348. if (e.Contains(SettingProperty.DetectMode))
  349. {
  350. Logger.Info($"Detect Mode:\"{SettingConfig.Instance.DetectMode}\"");
  351. if (_customizeDiagnosis != null)
  352. {
  353. _customizeDiagnosis.DetectMode = SettingConfig.Instance.DetectMode;
  354. }
  355. }
  356. }
  357. }
  358. if (e.Contains(SettingProperty.IsAsync) && !SettingConfig.Instance.IsVideo)
  359. {
  360. if (SettingConfig.Instance.IsEnableAI)
  361. {
  362. StartDiagnosis();
  363. if (SettingConfig.Instance.IsVideo == false)//当源文件为图片的情况下,就重新Show一次给AI提供图片信息。
  364. {
  365. DetectImage();
  366. }
  367. }
  368. }
  369. }
  370. private void CleanAIResult()
  371. {
  372. RemoveOldCache();
  373. Dispatcher.Invoke(() =>
  374. {
  375. ResultInfoText.Text = "";
  376. ElapsedTimeText.Text = "";
  377. });
  378. }
  379. private void UpdateTransforms()
  380. {
  381. if (_image != null)
  382. {
  383. // 使图片保持长宽比例,居中显示,需要平移和缩放
  384. var imgWidth = _image.Width;
  385. var imgHeight = _image.Height;
  386. var canvasWidth = UsCanvas.ActualWidth;
  387. var canvasHeight = UsCanvas.ActualHeight;
  388. var scaleX = canvasWidth / imgWidth;
  389. var scaleY = canvasHeight / imgHeight;
  390. var scale = scaleX < scaleY ? scaleX : scaleY;
  391. double offsetX, offsetY;
  392. if (Math.Abs(scale - scaleX) < 0.0001)
  393. {
  394. offsetY = 0.5 * (scaleY - scale) * imgHeight;
  395. offsetX = 0;
  396. }
  397. else
  398. {
  399. offsetX = 0.5 * (scaleX - scale) * imgWidth;
  400. offsetY = 0;
  401. }
  402. _transform = new MyTransform(scale, offsetX, offsetY);
  403. }
  404. }
  405. private void UpdateOrgans()
  406. {
  407. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  408. {
  409. if (_organs != null)
  410. {
  411. for (int ni = 0; ni < _organs.Count; ni++)
  412. {
  413. DrawOrganInCanvas(_organs[ni]);
  414. }
  415. }
  416. }));
  417. }
  418. private void RemoveOrgans()
  419. {
  420. Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
  421. {
  422. // 移除所有旧的Organ
  423. if (_organs != null)
  424. {
  425. for (int ni = 0; ni < _organs.Count; ni++)
  426. {
  427. RemoveOrganInCanvas(_organs[ni]);
  428. }
  429. }
  430. }));
  431. }
  432. private void DrawOrganInCanvas(Organ organ)
  433. {
  434. if (_transform == null)
  435. {
  436. return;
  437. }
  438. // 已有则删除
  439. RemoveOrganInCanvas(organ);
  440. if (organ.BoundBox == null)
  441. {
  442. return;
  443. }
  444. // 有轮廓就显示轮廓,没有轮廓就显示方框
  445. string organName = organ.OrganName;
  446. var rect = new System.Windows.Rect(organ.BoundBox.Left, organ.BoundBox.Top, organ.BoundBox.Width, organ.BoundBox.Height);
  447. var transRect = _transform.Transform(rect);
  448. System.Windows.Shapes.Rectangle rectDraw = new System.Windows.Shapes.Rectangle
  449. {
  450. StrokeThickness = 3,
  451. Stroke = organ.Color,
  452. Width = transRect.Width,
  453. Height = transRect.Height
  454. };
  455. Canvas.SetLeft(rectDraw, transRect.Left);
  456. Canvas.SetTop(rectDraw, transRect.Top);
  457. UsCanvas.Children.Add(rectDraw);
  458. string rectName = "Organ_Rect_" + organName;
  459. UsCanvas.RegisterName(rectName, rectDraw);
  460. // 将Organ的序号写在左上角
  461. var pointLT = new Point(organ.BoundBox.Left, organ.BoundBox.Top);
  462. var transPointLT = _transform.Transform(pointLT);
  463. var textLeft = transPointLT.X + 16;
  464. var textTop = transPointLT.Y;
  465. TextBlock text = new TextBlock
  466. {
  467. Text = organName,
  468. FontSize = 16,
  469. FontWeight = FontWeights.Bold,
  470. Foreground = organ.Color,
  471. VerticalAlignment = VerticalAlignment.Top
  472. };
  473. Canvas.SetLeft(text, textLeft);
  474. Canvas.SetTop(text, textTop);
  475. UsCanvas.Children.Add(text);
  476. string textName = "Organ_Text_" + organName;
  477. UsCanvas.RegisterName(textName, text);
  478. }
  479. private void RemoveOrganInCanvas(Organ organ)
  480. {
  481. string organName = organ.OrganName;
  482. // 框
  483. string rectName = "Organ_Rect_" + organName;
  484. RemoveElement(rectName);
  485. // 文字
  486. string textName = "Organ_Text_" + organName;
  487. RemoveElement(textName);
  488. }
  489. private void Window_StateChanged(object sender, EventArgs e)
  490. {
  491. if (WindowState == WindowState.Maximized)
  492. {
  493. MaxButton.Visibility = Visibility.Collapsed;
  494. RestoreButton.Visibility = Visibility.Visible;
  495. }
  496. else
  497. {
  498. MaxButton.Visibility = Visibility.Visible;
  499. RestoreButton.Visibility = Visibility.Collapsed;
  500. }
  501. }
  502. private void OnOpenSettingWindow(object sender, RoutedEventArgs e)
  503. {
  504. _settingWindow = new SettingWindow();
  505. _settingWindow.ShowDialog();
  506. }
  507. private void OnMinClick(object sender, RoutedEventArgs e)
  508. {
  509. WindowState = WindowState.Minimized;
  510. }
  511. private void OnMaxClick(object sender, RoutedEventArgs e)
  512. {
  513. WindowState = WindowState.Maximized;
  514. }
  515. private void OnRestoreClick(object sender, RoutedEventArgs e)
  516. {
  517. WindowState = WindowState.Normal;
  518. }
  519. private void OnCloseClick(object sender, RoutedEventArgs e)
  520. {
  521. if (_player != null)
  522. {
  523. _player.Stop();
  524. _player.InputFrameReceived -= OnInputFrameReceived;
  525. _player.FPSChanged -= OnFPSChanged;
  526. }
  527. CloseDiagnosis();
  528. Close();
  529. }
  530. private void Grid_MouseMove(object sender, MouseEventArgs e)
  531. {
  532. if (SettingConfig.Instance.IsVideo)
  533. {
  534. if (_isPlaying)
  535. {
  536. PauseButton.Visibility = Visibility.Visible;
  537. }
  538. }
  539. }
  540. private void CanvasSizeChanged(object sender, SizeChangedEventArgs e)
  541. {
  542. UpdateTransforms();
  543. RemoveOrgans();
  544. UpdateOrgans();
  545. }
  546. private void OnPlayClick(object sender, RoutedEventArgs e)
  547. {
  548. if (_player != null)
  549. {
  550. _player.Continue();
  551. _isPlaying = true;
  552. PlayButton.Visibility = Visibility.Collapsed;
  553. PauseButton.Visibility = Visibility.Visible;
  554. }
  555. }
  556. private void OnPauseClick(object sender, RoutedEventArgs e)
  557. {
  558. if (_player != null)
  559. {
  560. _player.Pause();
  561. _isPlaying = false;
  562. PlayButton.Visibility = Visibility.Visible;
  563. PauseButton.Visibility = Visibility.Collapsed;
  564. System.Threading.Tasks.Task.Run(() =>
  565. {
  566. Thread.Sleep(1000);
  567. DetectImage();
  568. });
  569. }
  570. }
  571. private void RemoveElement(string name)
  572. {
  573. var uiElement = UsCanvas.FindName(name) as UIElement;
  574. if (uiElement != null)
  575. {
  576. UsCanvas.Children.Remove(uiElement);
  577. UsCanvas.UnregisterName(name);
  578. }
  579. }
  580. private void Grid_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e)
  581. {
  582. PauseButton.Visibility = Visibility.Collapsed;
  583. }
  584. }
  585. }