MainWindow.xaml.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762
  1. using System;
  2. using System.IO;
  3. using System.Windows;
  4. using System.Drawing;
  5. using System.Threading;
  6. using Microsoft.Win32;
  7. using System.Windows.Threading;
  8. using System.Collections.Generic;
  9. using Accord.Video.FFMPEG;
  10. using AI.DiagSystem.Workers;
  11. using AI.DiagSystem.Workers.WorkerInputs;
  12. using ImageShowUtilsLib;
  13. using AI.Common;
  14. using AI.Common.Log;
  15. using AI.DiagSystem;
  16. namespace AIMultiInferWorkDemo
  17. {
  18. /// <summary>
  19. /// 图像相关信息
  20. /// </summary>
  21. public class ImageSourceFileInfo
  22. {
  23. private VideoFileReader _videoReader;
  24. public string OrigPath { get; protected set; }
  25. public bool IsVideo { get; protected set; }
  26. public int ImageCount { get; protected set; }
  27. public Bitmap GetOrigImage(int index = 0)
  28. {
  29. if (!File.Exists(OrigPath))
  30. {
  31. return null;
  32. }
  33. if (IsVideo)
  34. {
  35. if (index >= ImageCount)
  36. {
  37. return null;
  38. }
  39. var img = _videoReader.ReadVideoFrame(index);
  40. return img;
  41. }
  42. else
  43. {
  44. var img = new Bitmap(OrigPath);
  45. return img;
  46. }
  47. }
  48. public ImageSourceFileInfo(string origImagePath)
  49. {
  50. OrigPath = origImagePath;
  51. // 是否为视频
  52. FileInfo fileInfo = new FileInfo(origImagePath);
  53. IsVideo = false;
  54. if ((fileInfo.Extension == ".mp4") || (fileInfo.Extension == ".avi") || (fileInfo.Extension == ".wmv")
  55. || (fileInfo.Extension == ".MP4") || (fileInfo.Extension == ".AVI") || (fileInfo.Extension == ".WMV"))
  56. {
  57. IsVideo = true;
  58. }
  59. // 如果是视频,需要_videoReader打开它
  60. if (IsVideo)
  61. {
  62. _videoReader = new VideoFileReader();
  63. _videoReader.Open(origImagePath);
  64. if (_videoReader.CodecName == ".wmv2")
  65. {
  66. int count = 0;
  67. while (_videoReader.ReadVideoFrame(count) != null)
  68. {
  69. count += 1;
  70. }
  71. ImageCount = count;
  72. }
  73. else
  74. {
  75. ImageCount = (int)_videoReader.FrameCount;
  76. }
  77. }
  78. else
  79. {
  80. ImageCount = 1;
  81. }
  82. }
  83. public void Dispose()
  84. {
  85. if (_videoReader != null)
  86. {
  87. _videoReader.Close();
  88. _videoReader.Dispose();
  89. _videoReader = null;
  90. }
  91. }
  92. }
  93. /// <summary>
  94. /// MainWindow.xaml 的交互逻辑
  95. /// </summary>
  96. public partial class MainWindow : Window
  97. {
  98. #region private variables
  99. private WorkerManager _workManager = null;
  100. private AI.DiagSystem.ResultsAggregator _resultAggregator = null;
  101. private const int _numWorker = 2;
  102. private const int _modelCPU = 2;
  103. private const int _calCPU = 1;
  104. private const int _sleepTime = 500;
  105. private const bool _isCropped = false;
  106. private volatile bool _disposing = false;
  107. private volatile bool _loaded = false;
  108. private volatile EnumInferWorkName _inferWorkName1;
  109. private volatile EnumInferWorkName _inferWorkName2;
  110. private volatile ImageSourceFileInfo _imageSource1 = null;
  111. private volatile int _index1 = 0;
  112. private Thread _videoPlayThread1 = null;
  113. private volatile bool _videoPlaying1 = false;
  114. private volatile bool _stopVideoPlay1 = false;
  115. private volatile bool _reuse1 = false;
  116. private volatile bool _enableLesionSeg1 = false;
  117. private volatile bool _enableDescription1 = false;
  118. private volatile ImageSourceFileInfo _imageSource2 = null;
  119. private volatile int _index2 = 0;
  120. private Thread _videoPlayThread2 = null;
  121. private volatile bool _videoPlaying2 = false;
  122. private volatile bool _stopVideoPlay2 = false;
  123. private volatile bool _reuse2 = false;
  124. private volatile bool _enableLesionSeg2 = false;
  125. private volatile bool _enableDescription2 = false;
  126. private volatile bool _errorMsgShowing = false;
  127. #endregion
  128. #region 用户界面响应
  129. public MainWindow()
  130. {
  131. InitializeComponent();
  132. ComboBoxInferNames1.SelectionChanged -= OnInferNames1Changed;
  133. ComboBoxInferNames2.SelectionChanged -= OnInferNames2Changed;
  134. ComboBoxInferNames1.Items.Clear();
  135. ComboBoxInferNames2.Items.Clear();
  136. foreach (var inferName in Enum.GetValues(typeof(EnumInferWorkName)))
  137. {
  138. if ((EnumInferWorkName)inferName != EnumInferWorkName.Default &&
  139. (EnumInferWorkName)inferName != EnumInferWorkName.BreastDSOD &&
  140. (EnumInferWorkName)inferName != EnumInferWorkName.BreastDSOD_LiverYOLO &&
  141. (EnumInferWorkName)inferName != EnumInferWorkName.BreastDSOD_LiverKerasSeg &&
  142. (EnumInferWorkName)inferName != EnumInferWorkName.UserDefine2 &&
  143. (EnumInferWorkName)inferName != EnumInferWorkName.UserDefine3)
  144. {
  145. ComboBoxInferNames1.Items.Add(inferName);
  146. ComboBoxInferNames2.Items.Add(inferName);
  147. }
  148. }
  149. ComboBoxInferNames1.SelectionChanged += OnInferNames1Changed;
  150. ComboBoxInferNames2.SelectionChanged += OnInferNames2Changed;
  151. ComboBoxInferNames1.SelectedIndex = 0;
  152. ComboBoxInferNames2.SelectedIndex = 1;
  153. InitWorkManager();
  154. }
  155. private void OnBtnLoadImage1Click(object sender, RoutedEventArgs e)
  156. {
  157. if (!_loaded)
  158. {
  159. MessageBox.Show("请先加载模型.");
  160. return;
  161. }
  162. OpenFileDialog openFileDialog = new OpenFileDialog
  163. {
  164. Filter = "图片或视频|*.png;*.PNG;*.bmp;*.BMP;*.jpg;*.JPG;*.jpeg;*.JPEG;*.mp4;*.MP4;*.avi;*.AVI;*.wmv;*.WMV",
  165. Multiselect = false,
  166. Title = "选择一个图像或视频"
  167. };
  168. if (openFileDialog.ShowDialog() ?? false)
  169. {
  170. if (_imageSource1 != null)
  171. {
  172. if (_imageSource1.IsVideo && _videoPlaying1)
  173. {
  174. _stopVideoPlay1 = true;
  175. while (_videoPlaying1)
  176. {
  177. Thread.Sleep(5);
  178. }
  179. }
  180. _imageSource1.Dispose();
  181. }
  182. _imageSource1 = new ImageSourceFileInfo(openFileDialog.FileName);
  183. _index1 = 0;
  184. if (_imageSource1.IsVideo)
  185. {
  186. _videoPlaying1 = true;
  187. BtnStop1.Visibility = Visibility.Visible;
  188. BtnStop1.Content = "暂停";
  189. CheckBoxReuse1.Visibility = Visibility.Visible;
  190. if (_videoPlayThread1 == null || !_videoPlayThread1.IsAlive)
  191. {
  192. _videoPlayThread1 = new Thread(() => DoVideoPlay1())
  193. {
  194. IsBackground = true,
  195. Name = "AI_VideoPlay_1"
  196. };
  197. _videoPlayThread1.Start();
  198. }
  199. }
  200. else
  201. {
  202. BtnStop1.Visibility = Visibility.Hidden;
  203. CheckBoxReuse1.Visibility = Visibility.Hidden;
  204. TestOneFrame1();
  205. }
  206. }
  207. }
  208. private void OnBtnStop1Click(object sender, RoutedEventArgs e)
  209. {
  210. if (!_loaded)
  211. {
  212. MessageBox.Show("请先加载模型.");
  213. return;
  214. }
  215. if (_videoPlaying1)
  216. {
  217. BtnStop1.Content = "继续";
  218. _videoPlaying1 = false;
  219. }
  220. else
  221. {
  222. BtnStop1.Content = "暂停";
  223. _videoPlaying1 = true;
  224. if (_videoPlayThread1 == null || !_videoPlayThread1.IsAlive)
  225. {
  226. _videoPlayThread1 = new Thread(() => DoVideoPlay1())
  227. {
  228. IsBackground = true,
  229. Name = "AI_VideoPlay_1"
  230. };
  231. _videoPlayThread1.Start();
  232. }
  233. }
  234. }
  235. private void OnUncheckedReuse1(object sender, RoutedEventArgs e)
  236. {
  237. _reuse1 = false;
  238. }
  239. private void OnCheckedReuse1(object sender, RoutedEventArgs e)
  240. {
  241. _reuse1 = true;
  242. }
  243. private void OnUncheckedEnabelLesionSeg1(object sender, RoutedEventArgs e)
  244. {
  245. _enableLesionSeg1 = false;
  246. }
  247. private void OnCheckedEnableLesionSeg1(object sender, RoutedEventArgs e)
  248. {
  249. _enableLesionSeg1 = true;
  250. }
  251. private void OnUncheckedEnableDescription1(object sender, RoutedEventArgs e)
  252. {
  253. _enableDescription1 = false;
  254. }
  255. private void OnCheckedEnableDescription1(object sender, RoutedEventArgs e)
  256. {
  257. _enableDescription1 = true;
  258. }
  259. private void OnBtnLoadImage2Click(object sender, RoutedEventArgs e)
  260. {
  261. if (!_loaded)
  262. {
  263. MessageBox.Show("请先加载模型.");
  264. return;
  265. }
  266. OpenFileDialog openFileDialog = new OpenFileDialog
  267. {
  268. Filter = "图片或视频|*.png;*.PNG;*.bmp;*.BMP;*.jpg;*.JPG;*.jpeg;*.JPEG;*.mp4;*.MP4;*.avi;*.AVI;*.wmv;*.WMV",
  269. Multiselect = false,
  270. Title = "选择一个图像或视频"
  271. };
  272. if (openFileDialog.ShowDialog() ?? false)
  273. {
  274. if (_imageSource2 != null)
  275. {
  276. if (_imageSource2.IsVideo && _videoPlaying2)
  277. {
  278. _stopVideoPlay2 = true;
  279. while (_videoPlaying2)
  280. {
  281. Thread.Sleep(5);
  282. }
  283. }
  284. _imageSource2.Dispose();
  285. }
  286. _imageSource2 = new ImageSourceFileInfo(openFileDialog.FileName);
  287. _index2 = 0;
  288. if (_imageSource2.IsVideo)
  289. {
  290. _videoPlaying2 = true;
  291. BtnStop2.Visibility = Visibility.Visible;
  292. BtnStop2.Content = "暂停";
  293. CheckBoxReuse2.Visibility = Visibility.Visible;
  294. if (_videoPlayThread2 == null || !_videoPlayThread2.IsAlive)
  295. {
  296. _videoPlayThread2 = new Thread(() => DoVideoPlay2())
  297. {
  298. IsBackground = true,
  299. Name = "AI_VideoPlay_2"
  300. };
  301. _videoPlayThread2.Start();
  302. }
  303. }
  304. else
  305. {
  306. BtnStop2.Visibility = Visibility.Hidden;
  307. CheckBoxReuse2.Visibility = Visibility.Hidden;
  308. TestOneFrame2();
  309. }
  310. }
  311. }
  312. private void OnBtnStop2Click(object sender, RoutedEventArgs e)
  313. {
  314. if (!_loaded)
  315. {
  316. MessageBox.Show("请先加载模型.");
  317. return;
  318. }
  319. if (_videoPlaying2)
  320. {
  321. BtnStop2.Content = "继续";
  322. _videoPlaying2 = false;
  323. }
  324. else
  325. {
  326. BtnStop2.Content = "暂停";
  327. _videoPlaying2 = true;
  328. if (_videoPlayThread2 == null || !_videoPlayThread2.IsAlive)
  329. {
  330. _videoPlayThread2 = new Thread(() => DoVideoPlay2())
  331. {
  332. IsBackground = true,
  333. Name = "AI_VideoPlay_2"
  334. };
  335. _videoPlayThread2.Start();
  336. }
  337. }
  338. }
  339. private void OnUncheckedReuse2(object sender, RoutedEventArgs e)
  340. {
  341. _reuse2 = false;
  342. }
  343. private void OnCheckedReuse2(object sender, RoutedEventArgs e)
  344. {
  345. _reuse2 = true;
  346. }
  347. private void OnUncheckedEnabelLesionSeg2(object sender, RoutedEventArgs e)
  348. {
  349. _enableLesionSeg2 = false;
  350. }
  351. private void OnCheckedEnableLesionSeg2(object sender, RoutedEventArgs e)
  352. {
  353. _enableLesionSeg2 = true;
  354. }
  355. private void OnUncheckedEnableDescription2(object sender, RoutedEventArgs e)
  356. {
  357. _enableDescription2 = false;
  358. }
  359. private void OnCheckedEnableDescription2(object sender, RoutedEventArgs e)
  360. {
  361. _enableDescription2 = true;
  362. }
  363. private void OnInferNames1Changed(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
  364. {
  365. _loaded = false;
  366. _inferWorkName1 = (EnumInferWorkName)ComboBoxInferNames1.SelectedItem;
  367. }
  368. private void OnInferNames2Changed(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
  369. {
  370. _loaded = false;
  371. _inferWorkName2 = (EnumInferWorkName)ComboBoxInferNames2.SelectedItem;
  372. }
  373. private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
  374. {
  375. DoDispose();
  376. }
  377. private void OnBtnDisposeClick(object sender, RoutedEventArgs e)
  378. {
  379. DoDispose();
  380. }
  381. private void OnBtnLoadClick(object sender, RoutedEventArgs e)
  382. {
  383. InitWorkManager();
  384. }
  385. #endregion
  386. #region private
  387. /// <summary>
  388. /// 初始化workmanager
  389. /// </summary>
  390. private void InitWorkManager()
  391. {
  392. // 初始化workManager
  393. _workManager = new WorkerManager(25, _numWorker, _modelCPU, _calCPU, "",new List<EnumInferWorkName> { _inferWorkName1,_inferWorkName2});
  394. _workManager.NotifyInferFinish += OnWorkerInferFinish;
  395. _workManager.NotifyError += OnErrorOccur;
  396. _workManager.NotifyLog += OnLogWrite;
  397. // 初始化resultAggregator
  398. _resultAggregator = new AI.DiagSystem.ResultsAggregator(false, -1);
  399. _resultAggregator.NotifyLog += OnLogWrite;
  400. _loaded = true;
  401. _disposing = false;
  402. _stopVideoPlay1 = false;
  403. _stopVideoPlay2 = false;
  404. }
  405. /// <summary>
  406. /// 收到workManager的推理结束通知
  407. /// </summary>
  408. /// <param name="sender"></param>
  409. /// <param name="e"></param>
  410. private void OnWorkerInferFinish(object sender, InferFinishEventArgs e)
  411. {
  412. if (!_disposing)
  413. {
  414. _resultAggregator.AddInferResult(e.WorkerResult);
  415. UpdateInferTime(e.TimeElapsed, e.InferSize);
  416. }
  417. }
  418. /// <summary>
  419. /// 收到发生错误的通知
  420. /// </summary>
  421. /// <param name="sender"></param>
  422. /// <param name="e"></param>
  423. private void OnErrorOccur(object sender, ErrorEventArgs e)
  424. {
  425. if (!_errorMsgShowing)
  426. {
  427. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
  428. {
  429. _errorMsgShowing = true;
  430. MessageBox.Show("推理过程中发生错误!" + e.GetException());
  431. _errorMsgShowing = false;
  432. }));
  433. }
  434. }
  435. /// <summary>
  436. /// 有log要记
  437. /// </summary>
  438. /// <param name="sender"></param>
  439. /// <param name="e"></param>
  440. private void OnLogWrite(object sender, LogEventArgs e)
  441. {
  442. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
  443. {
  444. TextLog.Text += e.Msg +"\r\n";
  445. }));
  446. }
  447. /// <summary>
  448. /// 播放视频1
  449. /// </summary>
  450. private void DoVideoPlay1()
  451. {
  452. while (!_disposing)
  453. {
  454. if (_stopVideoPlay1)
  455. {
  456. _videoPlaying1 = false;
  457. _stopVideoPlay1 = false;
  458. }
  459. else
  460. {
  461. if (_videoPlaying1 && _imageSource1 != null)
  462. {
  463. if (!_imageSource1.IsVideo)
  464. {
  465. Thread.Sleep(5);
  466. continue;
  467. }
  468. if (_index1 <= -1)
  469. {
  470. Thread.Sleep(5);
  471. continue;
  472. }
  473. TestOneFrame1();
  474. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
  475. {
  476. ProgressBar1.Value = (int)((double)_index1 / _imageSource1.ImageCount * 100);
  477. }));
  478. // 更新index
  479. if (_index1 < _imageSource1.ImageCount - 1)
  480. {
  481. _index1 += 1;
  482. }
  483. else
  484. {
  485. if (_reuse1)
  486. {
  487. _index1 = 0;
  488. }
  489. else
  490. {
  491. _index1 = -1;
  492. }
  493. }
  494. Thread.Sleep(_sleepTime);
  495. }
  496. else
  497. {
  498. Thread.Sleep(5);
  499. }
  500. }
  501. }
  502. _videoPlaying1 = false;
  503. }
  504. /// <summary>
  505. /// 播放视频2
  506. /// </summary>
  507. private void DoVideoPlay2()
  508. {
  509. while (!_disposing)
  510. {
  511. if (_stopVideoPlay2)
  512. {
  513. _videoPlaying2 = false;
  514. _stopVideoPlay2 = false;
  515. }
  516. else
  517. {
  518. if (_videoPlaying2 && _imageSource2 != null)
  519. {
  520. if (!_imageSource2.IsVideo)
  521. {
  522. Thread.Sleep(5);
  523. continue;
  524. }
  525. if (_index2 <= -1)
  526. {
  527. Thread.Sleep(5);
  528. continue;
  529. }
  530. TestOneFrame2();
  531. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
  532. {
  533. ProgressBar2.Value = (int)((double)_index2 / _imageSource2.ImageCount * 100);
  534. }));
  535. // 更新index
  536. if (_index2 < _imageSource2.ImageCount - 1)
  537. {
  538. _index2 += 1;
  539. }
  540. else
  541. {
  542. if (_reuse2)
  543. {
  544. _index2 = 0;
  545. }
  546. else
  547. {
  548. _index2 = -1;
  549. }
  550. }
  551. Thread.Sleep(_sleepTime);
  552. }
  553. else
  554. {
  555. Thread.Sleep(5);
  556. }
  557. }
  558. }
  559. _videoPlaying2 = false;
  560. }
  561. /// <summary>
  562. /// 评估单幅图像
  563. /// 推理请求被塞入待处理队列后,等待诊断系统给出结果后再返回
  564. /// </summary>
  565. /// <param name="image"></param>
  566. /// <param name="isCropped"></param>
  567. /// <param name="scanPart"></param>
  568. /// <returns></returns>
  569. private AIDiagResultPerImg EvaluateOneImage(RawImage image, bool isCropped, bool enableLesionSeg, bool enableDescription, EnumScanParts scanPart, EnumInferWorkName inferTaskName)
  570. {
  571. // 生成随机码,作为diagId和inferId
  572. string diagId = Guid.NewGuid().ToString();
  573. WorkerInputBatchImages input = new WorkerInputBatchImages(diagId, diagId,
  574. new RawImage(image.DataBuffer, image.Width, image.Height, image.ColorType),
  575. isCropped,enableLesionSeg, enableDescription, scanPart,inferTaskName);
  576. _workManager.AddInferRequest(input);
  577. // 将相关信息塞入结果收集器
  578. _resultAggregator.AddNewDiag(diagId, 1, isCropped,enableLesionSeg, enableDescription,scanPart, inferTaskName);
  579. _resultAggregator.AddNewInfer(diagId, diagId, 1);
  580. // 等待结果
  581. AI.DiagSystem.AIDiagResultPerImg result = null;
  582. bool waiting = true;
  583. while (waiting && !_disposing)
  584. {
  585. if (!_resultAggregator.GetIsFinish(diagId))
  586. {
  587. Thread.Sleep(5);
  588. }
  589. else
  590. {
  591. waiting = false;
  592. var ret = (AI.DiagSystem.AIDiagResultBatchImages)_resultAggregator.GetDiagResults(diagId);
  593. result = ret.DiagResult[0];
  594. }
  595. }
  596. return result;
  597. }
  598. /// <summary>
  599. /// 将结果画到图上
  600. /// </summary>
  601. /// <param name="image"></param>
  602. /// <param name="diagResult"></param>
  603. /// <param name="inferWorkName"></param>
  604. private void DrawResultOnImage(Bitmap image, AI.DiagSystem.AIDiagResultPerImg diagResult)
  605. {
  606. try
  607. {
  608. ResultShowGrid.UpdateImage(image);
  609. ResultShowGrid.UpdateDiagResult(diagResult);
  610. }
  611. catch (Exception excep)
  612. {
  613. MessageBox.Show("出错了:" + excep);
  614. }
  615. }
  616. /// <summary>
  617. /// 将推理耗时显示到界面上
  618. /// </summary>
  619. /// <param name="inferTime"></param>
  620. private void UpdateInferTime(Dictionary<string, int> inferTime, int inferSize)
  621. {
  622. string inferTimePerTask = "";
  623. foreach (var taskname in inferTime.Keys)
  624. {
  625. inferTimePerTask += "{'" + taskname + "':" + inferTime[taskname].ToString() + "}\r\n";
  626. }
  627. string inferTimeStr = "InferSize:" + inferSize + ",\r\nInferTimePerTask:\r\n" + inferTimePerTask;
  628. Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
  629. {
  630. TextInferTime.Text = inferTimeStr;
  631. }));
  632. }
  633. private void DoDispose()
  634. {
  635. try
  636. {
  637. _disposing = true;
  638. _stopVideoPlay1 = true;
  639. while (_videoPlaying1)
  640. {
  641. Thread.Sleep(5);
  642. }
  643. _imageSource1?.Dispose();
  644. _stopVideoPlay2 = true;
  645. while (_videoPlaying2)
  646. {
  647. Thread.Sleep(5);
  648. }
  649. _imageSource2?.Dispose();
  650. _workManager?.Dispose();
  651. _resultAggregator?.Dispose();
  652. _loaded = false;
  653. }
  654. catch (Exception excep)
  655. {
  656. MessageBox.Show("释放时出错:" + excep);
  657. }
  658. }
  659. private void TestOneFrame1()
  660. {
  661. // 取出当前图像
  662. Bitmap image = _imageSource1.GetOrigImage(_index1);
  663. // 测试
  664. var rawImg = RawImageShowUtils.BitmapToRawImage(image);
  665. RawImage rawImage = new RawImage(rawImg.DataBuffer, rawImg.Width, rawImg.Height, rawImg.ColorType);
  666. EnumInferWorkName inferWorkName = _inferWorkName1;
  667. var result = EvaluateOneImage(rawImage, _isCropped, _enableLesionSeg1, _enableDescription1, EnumScanParts.NotSpecified, inferWorkName);
  668. rawImage.Dispose();
  669. rawImg.Dispose();
  670. if (result == null)
  671. {
  672. image.Dispose();
  673. return;
  674. }
  675. // 更新显示
  676. DrawResultOnImage(image, result);
  677. image.Dispose();
  678. }
  679. private void TestOneFrame2()
  680. {
  681. // 取出当前图像
  682. Bitmap image = _imageSource2.GetOrigImage(_index2);
  683. // 测试
  684. var rawImg = RawImageShowUtils.BitmapToRawImage(image);
  685. RawImage rawImage = new RawImage(rawImg.DataBuffer, rawImg.Width, rawImg.Height, rawImg.ColorType);
  686. EnumInferWorkName inferWorkName = _inferWorkName2;
  687. var result = EvaluateOneImage(rawImage, _isCropped, _enableLesionSeg2, _enableDescription2, EnumScanParts.NotSpecified, inferWorkName);
  688. rawImage.Dispose();
  689. rawImg.Dispose();
  690. if (result == null)
  691. {
  692. image.Dispose();
  693. return;
  694. }
  695. // 更新显示
  696. DrawResultOnImage(image, result);
  697. image.Dispose();
  698. }
  699. #endregion
  700. }
  701. }