MainWindow.xaml.cs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. using System;
  2. using System.Windows;
  3. using System.Threading;
  4. using System.Threading.Tasks;
  5. using System.IO;
  6. using System.Collections.Generic;
  7. using Microsoft.Win32;
  8. using System.Drawing;
  9. using Accord.Video;
  10. using Accord.Video.FFMPEG;
  11. using Accord.Video.DirectShow;
  12. using UsHepatoRenalRatioDetectLib;
  13. using AI.Common;
  14. using AI.Common.Log;
  15. using Rect = AI.Common.Rect;
  16. using ImageShowUtilsLib;
  17. using System.Windows.Media.Imaging;
  18. using System.Windows.Input;
  19. using System.Windows.Media;
  20. using System.Xml.Linq;
  21. using System.ComponentModel;
  22. using Rectangle = System.Drawing.Rectangle;
  23. #test
  24. namespace HepatoRenalEchoContrastDemo
  25. {
  26. public enum TestType
  27. {
  28. None,
  29. ImageTest,
  30. VideoTest,
  31. CardTest
  32. }
  33. /// <summary>
  34. /// MainWindow.xaml 的交互逻辑
  35. /// </summary>
  36. public partial class MainWindow : Window
  37. {
  38. #region private
  39. private volatile bool _showOrganSeg = true;
  40. private volatile bool _showRois = false;
  41. private volatile bool _showEchoContrastValue = true;
  42. private IUsHepatoRenalRatioDetect _echoContrastDetect;
  43. private ManualResetEvent _playEvent = new ManualResetEvent(false);
  44. private VideoFileReader _videoReader;
  45. private readonly object _videoReaderLocker = new object();
  46. private VideoCaptureDevice _videoCapture;
  47. private volatile int _frameIntervalTime = 0;
  48. private volatile bool _readingVideo = true; //false
  49. private volatile bool _pausing = false;
  50. private volatile int _frameCount = 0;
  51. private volatile int _frameIndex = 0;
  52. private Thread _videoPlayThread = null;
  53. private volatile int _lastDetectTickCount;
  54. private volatile int _fpsStartTickCount;
  55. private volatile int _displayCount = 0;
  56. private volatile bool _continuouslyDetecting = false;
  57. private ManualResetEvent _videoPlayEvent = new ManualResetEvent(false);
  58. /// ///////////////////////////////////////////////
  59. private bool _isCropImag;
  60. private volatile TestType _testType = TestType.None;
  61. private bool _isManulSelROI; // 是否选择手动画框
  62. // 鼠标动作
  63. //private volatile EnumMouseOperType _mouseOper = EnumMouseOperType.None;
  64. private volatile bool _mouseLeftBtnPressed = false;
  65. // 鼠标绘制的起始位置(画线时需要)
  66. private System.Windows.Point _mouseStartPos;
  67. // 绘制中的所有轮廓点的集合
  68. private List<System.Windows.Point> _drawingPoints = new List<System.Windows.Point>();
  69. private Point2D _mousePosInOrigImg = new Point2D(0, 0);
  70. private Point2D _startPosInOrigImg = new Point2D(0, 0);
  71. private List<Point2D> _contourInOrigImg = new List<Point2D>();
  72. private List<Rect> roisManual = new List<Rect>();
  73. private Bitmap _imageBuffer;
  74. private volatile bool _isEnableDetect = false; // 开启测试
  75. #endregion
  76. #region 用户界面响应
  77. public MainWindow()
  78. {
  79. InitializeComponent();
  80. CheckBoxShowOrganSeg.IsChecked = _showOrganSeg;
  81. CheckBoxShowRois.IsChecked = _showRois;
  82. CheckBoxShowEchoContrastValue.IsChecked = _showEchoContrastValue;
  83. //刷新采集卡
  84. RefreshComboBoxVideoCards();
  85. // todo
  86. MyImageCanvas.SetShowParams(_showOrganSeg, _showRois, _showEchoContrastValue);
  87. }
  88. /// <summary>
  89. /// 用户关闭窗口
  90. /// </summary>
  91. /// <param name="sender"></param>
  92. /// <param name="e"></param>
  93. private void OnWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
  94. {
  95. StopPlay();
  96. _isEnableDetect = false;
  97. if (_echoContrastDetect != null)
  98. {
  99. _echoContrastDetect.StopProcess();
  100. _echoContrastDetect.NotifyError -= OnErrorOccur;
  101. _echoContrastDetect.NotifyLog -= OnLogWrite;
  102. _echoContrastDetect.NotifyProcessFinish -= OnPreprocessedDatasUpdate;
  103. _echoContrastDetect.Dispose();
  104. _echoContrastDetect = null;
  105. }
  106. if (_imageBuffer != null)
  107. {
  108. _imageBuffer.Dispose();
  109. _imageBuffer = null;
  110. }
  111. }
  112. /// <summary>
  113. /// 显示器官分割
  114. /// </summary>
  115. /// <param name="sender"></param>
  116. /// <param name="e"></param>
  117. private void OnCheckBoxShowOrganSegChecked(object sender, RoutedEventArgs e)
  118. {
  119. _showOrganSeg = true;
  120. MyImageCanvas.SetShowParams(_showOrganSeg, _showRois, _showEchoContrastValue);
  121. }
  122. /// <summary>
  123. /// 不显示器官分割
  124. /// </summary>
  125. /// <param name="sender"></param>
  126. /// <param name="e"></param>
  127. private void OnCheckBoxShowOrganSegUnchecked(object sender, RoutedEventArgs e)
  128. {
  129. _showOrganSeg = false;
  130. MyImageCanvas.SetShowParams(_showOrganSeg, _showRois, _showEchoContrastValue);
  131. }
  132. /// <summary>
  133. /// 显示roi
  134. /// </summary>
  135. /// <param name="sender"></param>
  136. /// <param name="e"></param>
  137. private void OnCheckBoxShowRoisChecked(object sender, RoutedEventArgs e)
  138. {
  139. _showRois = true;
  140. MyImageCanvas.SetShowParams(_showOrganSeg, _showRois, _showEchoContrastValue);
  141. }
  142. /// <summary>
  143. /// 不显示roi
  144. /// </summary>
  145. /// <param name="sender"></param>
  146. /// <param name="e"></param>
  147. private void OnCheckBoxShowRoisUnchecked(object sender, RoutedEventArgs e)
  148. {
  149. _showRois = false;
  150. MyImageCanvas.SetShowParams(_showOrganSeg, _showRois, _showEchoContrastValue);
  151. }
  152. /// <summary>
  153. /// 显示肝肾比
  154. /// </summary>
  155. /// <param name="sender"></param>
  156. /// <param name="e"></param>
  157. private void OnCheckBoxShowEchoContrastValueChecked(object sender, RoutedEventArgs e)
  158. {
  159. _showEchoContrastValue = true;
  160. MyImageCanvas.SetShowParams(_showOrganSeg, _showRois, _showEchoContrastValue);
  161. }
  162. /// <summary>
  163. /// 不显示肝肾比
  164. /// </summary>
  165. /// <param name="sender"></param>
  166. /// <param name="e"></param>
  167. private void OnCheckBoxShowEchoContrastValueUnchecked(object sender, RoutedEventArgs e)
  168. {
  169. _showEchoContrastValue = false;
  170. MyImageCanvas.SetShowParams(_showOrganSeg, _showRois, _showEchoContrastValue);
  171. }
  172. private void OnCheckBoxIsCropChecked(object sender, RoutedEventArgs e)
  173. {
  174. _isCropImag = true;
  175. }
  176. private void OnCheckBoxIsCropUnchecked(object sender, RoutedEventArgs e)
  177. {
  178. _isCropImag = false;
  179. }
  180. /// <summary>
  181. /// 开启手动选框
  182. /// </summary>
  183. /// <param name="sender"></param>
  184. /// <param name="e"></param>
  185. private void OnCheckBoxIsManulSelectROIChecked(object sender, RoutedEventArgs e)
  186. {
  187. _isManulSelROI = true;
  188. BtnCleraRois.IsEnabled = true;
  189. BtnCalHRR.IsEnabled= true;
  190. BtnClearHRR.IsEnabled= true;
  191. BtnStartAutoDetect.IsEnabled = false;
  192. BtnStopAutoDetect.IsEnabled = false;
  193. }
  194. /// <summary>
  195. /// 停止手动选框
  196. /// </summary>
  197. /// <param name="sender"></param>
  198. /// <param name="e"></param>
  199. private void OnCheckBoxIsManulSelectROIUnchecked(object sender, RoutedEventArgs e)
  200. {
  201. _isManulSelROI = false;
  202. BtnCleraRois.IsEnabled = false;
  203. BtnCalHRR.IsEnabled = false;
  204. BtnClearHRR.IsEnabled = false;
  205. BtnStartAutoDetect.IsEnabled = true;
  206. BtnStopAutoDetect.IsEnabled = true;
  207. }
  208. /// <summary>
  209. /// 加载图片或视频
  210. /// </summary>
  211. /// <param name="sender"></param>
  212. /// <param name="e"></param>
  213. private void OnBtnLoadVideoClick(object sender, RoutedEventArgs e)
  214. {
  215. StopPlay();
  216. var ofd = new OpenFileDialog();
  217. ofd.Filter = "图像或视频|*.png;*.bmp;*.jpg;*.jpeg;*.mp4;*.avi";
  218. ofd.Multiselect = false;
  219. ofd.Title = "选择一幅图像或一个视频";
  220. if (ofd.ShowDialog() == true)
  221. {
  222. var fileName = ofd.FileName;
  223. var fileExtension = Path.GetExtension(fileName);
  224. if (fileExtension == ".png" || fileExtension == ".bmp" || fileExtension == ".jpg" || fileExtension == ".jpeg")
  225. {
  226. BtnPauseOrPlay.Content = "播放";
  227. var bitmap = new Bitmap(fileName);
  228. MyImageCanvas.UpdateImage(bitmap);
  229. if (_imageBuffer != null)
  230. {
  231. _imageBuffer.Dispose();
  232. }
  233. _imageBuffer = bitmap.Clone(new Rectangle(0, 0, bitmap.Width, bitmap.Height), bitmap.PixelFormat); ;
  234. bitmap.Dispose();
  235. _testType = TestType.ImageTest;
  236. }
  237. else
  238. {
  239. _testType = TestType.VideoTest;
  240. double frameRate;
  241. //long frameCount;
  242. lock (_videoReaderLocker)
  243. {
  244. _videoReader = new VideoFileReader();
  245. _videoReader.Open(fileName);
  246. frameRate = _videoReader.FrameRate.ToDouble();
  247. _frameCount = (int)_videoReader.FrameCount;
  248. }
  249. //var sleepTime = (int)(1000 / frameRate);
  250. _playEvent.Reset();
  251. _readingVideo = true;
  252. _pausing = false; // 默认自动播放
  253. ProgressBarVideoPlay.IsEnabled = true;
  254. BtnBack.IsEnabled = true;
  255. BtnPauseOrPlay.IsEnabled = true;
  256. BtnForward.IsEnabled = true;
  257. BtnPauseOrPlay.Content = "暂停";
  258. ProgressBarVideoPlay.Minimum = 0;
  259. ProgressBarVideoPlay.Maximum = _frameCount;
  260. _lastDetectTickCount = Environment.TickCount;
  261. _fpsStartTickCount = _lastDetectTickCount;
  262. _displayCount = 0;
  263. _frameIndex = 0;
  264. _playEvent.Reset();
  265. MyImageCanvas.ClearTestResult();
  266. if (_videoPlayThread == null || !_videoPlayThread.IsAlive)
  267. {
  268. _videoPlayThread = new Thread(() => DoVideoPlay())
  269. {
  270. IsBackground = true,
  271. Name = "AI_Myocardial_Segmentation_VideoPlay",
  272. };
  273. _videoPlayThread.Start();
  274. }
  275. }
  276. }
  277. }
  278. /// <summary>
  279. /// 被选择的采集卡有变
  280. /// </summary>
  281. /// <param name="sender"></param>
  282. /// <param name="e"></param>
  283. private void OnComboBoxCardsSelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
  284. {
  285. StopPlay();
  286. }
  287. /// <summary>
  288. /// 刷新所有采集卡
  289. /// </summary>
  290. /// <param name="sender"></param>
  291. /// <param name="e"></param>
  292. private void OnRefreshCardsClick(object sender, RoutedEventArgs e)
  293. {
  294. RefreshComboBoxVideoCards();
  295. }
  296. /// <summary>
  297. /// 打开采集卡
  298. /// </summary>
  299. /// <param name="sender"></param>
  300. /// <param name="e"></param>
  301. private void OnBtnOpenGrabClick(object sender, RoutedEventArgs e)
  302. {
  303. if (ComboBoxCards.SelectedIndex != -1)
  304. {
  305. _testType = TestType.CardTest;
  306. StopPlay();
  307. var device = (FilterInfo)ComboBoxCards.SelectedItem;
  308. _videoCapture = new VideoCaptureDevice(device.MonikerString);
  309. _videoCapture.NewFrame += OnVideoCaptureNewFrame;
  310. _videoCapture.Start();
  311. }
  312. else
  313. {
  314. MessageBox.Show("未检测到可用的视频采集设备!");
  315. }
  316. }
  317. /// <summary>
  318. /// 暂停或播放视频
  319. /// </summary>
  320. /// <param name="sender"></param>
  321. /// <param name="e"></param>
  322. private void OnBtnPauseOrPlayClick(object sender, RoutedEventArgs e)
  323. {
  324. if (!_readingVideo)
  325. {
  326. return;
  327. }
  328. if (_continuouslyDetecting)
  329. {
  330. // 停止自动播放
  331. _videoPlayEvent.Set();
  332. _pausing = true;
  333. BtnPauseOrPlay.Content = "播放";
  334. }
  335. else
  336. {
  337. // 开始自动播放
  338. _pausing = false;
  339. _videoPlayEvent.Reset();
  340. if (_videoPlayThread == null || !_videoPlayThread.IsAlive)
  341. {
  342. _videoPlayThread = new Thread(() => DoVideoPlay())
  343. {
  344. IsBackground = true,
  345. Name = "AI_Myocardial_Segmentation_VideoPlay",
  346. };
  347. _videoPlayThread.Start();
  348. }
  349. BtnPauseOrPlay.Content = "暂停";
  350. }
  351. }
  352. /// <summary>
  353. /// 前一帧
  354. /// </summary>
  355. /// <param name="sender"></param>
  356. /// <param name="e"></param>
  357. private void OnBtnBackClick(object sender, RoutedEventArgs e)
  358. {
  359. if (!_readingVideo)
  360. {
  361. return;
  362. }
  363. if (_continuouslyDetecting)
  364. {
  365. // 停止自动播放
  366. _videoPlayEvent.Set();
  367. _pausing = true;
  368. BtnPauseOrPlay.Content = "播放";
  369. }
  370. // 往后退一帧
  371. if (_frameIndex <= 0)
  372. {
  373. _frameIndex = _frameCount - 1;
  374. }
  375. else
  376. {
  377. _frameIndex -= 2;
  378. }
  379. ProgressBarVideoPlay.Value = _frameIndex;
  380. TextFrameIndex.Text = _frameIndex.ToString();
  381. // 显示当前帧
  382. Task.Run(() =>
  383. {
  384. Bitmap bitmap;
  385. lock (_videoReaderLocker)
  386. {
  387. bitmap = _videoReader.ReadVideoFrame(_frameIndex);
  388. }
  389. // 更新显示图像
  390. MyImageCanvas.UpdateImage(bitmap);
  391. DetectImage(bitmap);
  392. bitmap.Dispose();
  393. });
  394. }
  395. /// <summary>
  396. /// 后一帧
  397. /// </summary>
  398. /// <param name="sender"></param>
  399. /// <param name="e"></param>
  400. private void OnBtnForwardClick(object sender, RoutedEventArgs e)
  401. {
  402. if (!_readingVideo)
  403. {
  404. return;
  405. }
  406. if (_continuouslyDetecting)
  407. {
  408. // 停止自动播放
  409. _videoPlayEvent.Set();
  410. _pausing = true;
  411. BtnPauseOrPlay.Content = "播放";
  412. }
  413. // 往前走一帧
  414. if (_frameIndex >= _frameCount - 2)
  415. {
  416. _frameIndex = 0;
  417. }
  418. else
  419. {
  420. _frameIndex += 2;
  421. }
  422. ProgressBarVideoPlay.Value = _frameIndex;
  423. TextFrameIndex.Text = _frameIndex.ToString();
  424. // 显示当前帧
  425. Task.Run(() =>
  426. {
  427. Bitmap bitmap;
  428. lock (_videoReaderLocker)
  429. {
  430. bitmap = _videoReader.ReadVideoFrame(_frameIndex);
  431. }
  432. MyImageCanvas.UpdateImage(bitmap);
  433. DetectImage(bitmap);
  434. bitmap.Dispose();
  435. });
  436. }
  437. /// <summary>
  438. /// 清空手动框
  439. /// </summary>
  440. /// <param name="sender"></param>
  441. /// <param name="e"></param>
  442. private void OnBtnClearRoisClick(object sender, RoutedEventArgs e)
  443. {
  444. MyImageCanvas.RemoveRoiInCanvas("liver");
  445. MyImageCanvas.RemoveRoiInCanvas("kidney");
  446. roisManual.Clear();
  447. }
  448. /// <summary>
  449. /// 根据输入框计算Hrr
  450. /// </summary>
  451. /// <param name="sender"></param>
  452. /// <param name="e"></param>
  453. private void OnBtnCalHRRClick(object sender, RoutedEventArgs e)
  454. {
  455. if (_imageBuffer == null)
  456. {
  457. MessageBox.Show("请重新加载一张图片!");
  458. return;
  459. }
  460. if (roisManual.Count != 2)
  461. {
  462. MessageBox.Show("请先选择两个roi框");
  463. return;
  464. }
  465. if (_echoContrastDetect == null)
  466. {
  467. _echoContrastDetect = new UsHepatoRenalRatioDetect();
  468. _echoContrastDetect.NotifyError += OnErrorOccur;
  469. _echoContrastDetect.NotifyLog += OnLogWrite;
  470. _echoContrastDetect.NotifyProcessFinish += OnPreprocessedDatasUpdate;
  471. var rawImage = RawImageShowUtils.BitmapToRawImage(_imageBuffer);
  472. double ratio = _echoContrastDetect.GetHepatoRenalRatio(rawImage, roisManual[0], roisManual[1]);
  473. // 更新显示结果
  474. MyImageCanvas.UpdateTestResults(new HRRDetectResultPerImg(new SegResultPerOrgan[0], new Dictionary<EnumOrgans, Rect>(), ratio));
  475. }
  476. }
  477. /// <summary>
  478. /// 清空手动框结果
  479. /// </summary>
  480. /// <param name="sender"></param>
  481. /// <param name="e"></param>
  482. private void OnBtnClearHRRClick(object sender, RoutedEventArgs e)
  483. {
  484. if (_echoContrastDetect != null)
  485. {
  486. _echoContrastDetect.NotifyError -= OnErrorOccur;
  487. _echoContrastDetect.NotifyLog -= OnLogWrite;
  488. _echoContrastDetect.NotifyProcessFinish -= OnPreprocessedDatasUpdate;
  489. _echoContrastDetect.Dispose();
  490. _echoContrastDetect = null;
  491. }
  492. // 清除耗时显示
  493. Dispatcher.Invoke(() =>
  494. {
  495. TextTestTotalTime.Text = string.Empty;
  496. TextOrganSegTime.Text = string.Empty;
  497. UsImage.Source = null;
  498. });
  499. // 清除结果显示
  500. MyImageCanvas.RemoveRoiInCanvas("liver");
  501. MyImageCanvas.RemoveRoiInCanvas("kidney");
  502. roisManual.Clear();
  503. MyImageCanvas.ClearTestResult();
  504. }
  505. /// <summary>
  506. /// 开始处理
  507. /// </summary>
  508. /// <param name="sender"></param>
  509. /// <param name="e"></param>
  510. private void OnBtnStartProcessClick(object sender, RoutedEventArgs e)
  511. {
  512. if (_testType == TestType.None)
  513. {
  514. MessageBox.Show("请先选择待测试数据(图片/视频/实时超声数据)!");
  515. return;
  516. }
  517. if (_isManulSelROI)
  518. {
  519. if (_imageBuffer == null)
  520. {
  521. MessageBox.Show("请重新加载一张图片!");
  522. return;
  523. }
  524. if (roisManual.Count != 2)
  525. {
  526. MessageBox.Show("请先选择两个roi框");
  527. return;
  528. }
  529. if (_echoContrastDetect == null)
  530. {
  531. _echoContrastDetect = new UsHepatoRenalRatioDetect();
  532. _echoContrastDetect.NotifyError += OnErrorOccur;
  533. _echoContrastDetect.NotifyLog += OnLogWrite;
  534. _echoContrastDetect.NotifyProcessFinish += OnPreprocessedDatasUpdate;
  535. var rawImage = RawImageShowUtils.BitmapToRawImage(_imageBuffer);
  536. double ratio = _echoContrastDetect.GetHepatoRenalRatio(rawImage, roisManual[0], roisManual[1]);
  537. // 更新显示结果
  538. MyImageCanvas.UpdateTestResults(new HRRDetectResultPerImg(new SegResultPerOrgan[0], new Dictionary<EnumOrgans, Rect>() , ratio));
  539. }
  540. }
  541. else
  542. {
  543. if (_echoContrastDetect == null)
  544. {
  545. _echoContrastDetect = new UsHepatoRenalRatioDetect();
  546. _echoContrastDetect.NotifyError += OnErrorOccur;
  547. _echoContrastDetect.NotifyLog += OnLogWrite;
  548. _echoContrastDetect.NotifyProcessFinish += OnPreprocessedDatasUpdate;
  549. _echoContrastDetect.Init(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks"), _isCropImag);
  550. _echoContrastDetect.LoadInferNet();
  551. }
  552. _echoContrastDetect.StartProcess();
  553. // 做单张图片测试
  554. if (_testType == TestType.ImageTest)
  555. {
  556. if (_imageBuffer == null)
  557. {
  558. MessageBox.Show("请先选择图片!");
  559. return;
  560. }
  561. DetectImage(_imageBuffer);
  562. }
  563. _isEnableDetect = true;
  564. }
  565. }
  566. /// <summary>
  567. /// 停止处理
  568. /// </summary>
  569. /// <param name="sender"></param>
  570. /// <param name="e"></param>
  571. private void OnBtnStopProcessClick(object sender, RoutedEventArgs e)
  572. {
  573. _isEnableDetect = false;
  574. if (_echoContrastDetect != null)
  575. {
  576. _echoContrastDetect.StopProcess();
  577. _echoContrastDetect.NotifyError -= OnErrorOccur;
  578. _echoContrastDetect.NotifyLog -= OnLogWrite;
  579. _echoContrastDetect.NotifyProcessFinish -= OnPreprocessedDatasUpdate;
  580. _echoContrastDetect.Dispose();
  581. _echoContrastDetect = null;
  582. }
  583. // 清除耗时显示
  584. Dispatcher.Invoke(() =>
  585. {
  586. TextTestTotalTime.Text = string.Empty;
  587. TextOrganSegTime.Text = string.Empty;
  588. UsImage.Source = null;
  589. });
  590. // 清除结果显示
  591. MyImageCanvas.ClearTestResult();
  592. }
  593. #endregion
  594. #region private
  595. /// <summary>
  596. /// 刷新列表中的采集卡
  597. /// </summary>
  598. private void RefreshComboBoxVideoCards()
  599. {
  600. StopPlay();
  601. ComboBoxCards.Items.Clear();
  602. var videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
  603. foreach (var device in videoDevices)
  604. {
  605. ComboBoxCards.Items.Add(device);
  606. }
  607. if (ComboBoxCards.Items.Count > 0)
  608. {
  609. ComboBoxCards.SelectedIndex = 0;
  610. }
  611. }
  612. /// <summary>
  613. /// 采集卡采集到了一幅新的图像
  614. /// </summary>
  615. private void OnVideoCaptureNewFrame(object sender, NewFrameEventArgs e)
  616. {
  617. var bitmap = e.Frame;
  618. MyImageCanvas.UpdateImage(bitmap);
  619. // 这里是否要每一帧都塞到探头模块去测?(探头模块中来不及测的会自动忽略)
  620. //DetectImage(bitmap);
  621. bitmap.Dispose();
  622. }
  623. /// <summary>
  624. /// 播放视频
  625. /// </summary>
  626. private void DoVideoPlay()
  627. {
  628. _continuouslyDetecting = true;
  629. while (!_pausing)
  630. {
  631. var currentTickCount = Environment.TickCount;
  632. Bitmap bitmap;
  633. lock (_videoReaderLocker)
  634. {
  635. bitmap = _videoReader?.ReadVideoFrame(_frameIndex);
  636. }
  637. if (bitmap == null)
  638. {
  639. break;
  640. }
  641. MyImageCanvas.UpdateImage(bitmap);
  642. if (_isEnableDetect)
  643. {
  644. DetectImage(bitmap);
  645. }
  646. bitmap.Dispose();
  647. // 更新显示帧率
  648. _displayCount++;
  649. // 最后还剩多少时间sleep
  650. var detectTimeUsed = Environment.TickCount - currentTickCount;
  651. var finalSleepTime = _frameIntervalTime - detectTimeUsed;
  652. if (finalSleepTime < 0)
  653. {
  654. finalSleepTime = 0;
  655. }
  656. if (_videoPlayEvent.WaitOne(finalSleepTime))
  657. {
  658. break;
  659. }
  660. // 如果到尾了,就从头开始
  661. if (_frameIndex >= _frameCount - 2)
  662. {
  663. _frameIndex = 0;
  664. }
  665. else
  666. {
  667. _frameIndex += 2;
  668. }
  669. // 更新进度条
  670. Dispatcher.Invoke(() =>
  671. {
  672. ProgressBarVideoPlay.Value = _frameIndex;
  673. TextFrameIndex.Text = _frameIndex.ToString();
  674. });
  675. }
  676. _continuouslyDetecting = false;
  677. }
  678. /// <summary>
  679. /// 停止播放视频
  680. /// </summary>
  681. private void StopPlay()
  682. {
  683. _playEvent.Set();
  684. lock (_videoReaderLocker)
  685. {
  686. if (_videoReader != null)
  687. {
  688. _videoReader.Close();
  689. _videoReader.Dispose();
  690. _videoReader = null;
  691. }
  692. }
  693. if (_videoCapture != null)
  694. {
  695. _videoCapture.NewFrame -= OnVideoCaptureNewFrame;
  696. _videoCapture.SignalToStop();
  697. _videoCapture = null;
  698. }
  699. }
  700. /// <summary>
  701. /// 检测一幅图像
  702. /// </summary>
  703. /// <param name="image"></param>
  704. private void DetectImage(Bitmap image)
  705. {
  706. var rawImage = RawImageShowUtils.BitmapToRawImage(image);
  707. _echoContrastDetect.UpdateUsImage(rawImage);
  708. }
  709. /// <summary>
  710. /// 有结果更新
  711. /// </summary>
  712. /// <param name="sender"></param>
  713. /// <param name="e"></param>
  714. private void OnPreprocessedDatasUpdate(object sender, UsHRRDetectUpdateEvent e)
  715. {
  716. if (e.HRRProcessStatus != EnumHRRStatus.HRR_SUCCESSED)
  717. {
  718. MessageBox.Show("HRR检测失败!原因是:" + e.HRRProcessStatus.ToString());
  719. }
  720. else
  721. {
  722. //// 更新显示耗时
  723. string totalTime = string.Empty;
  724. string organSegTime = string.Empty;
  725. if (e.TimeElapsed.ContainsKey(EnumProcessTime.TotalTime))
  726. {
  727. totalTime = e.TimeElapsed[EnumProcessTime.TotalTime].ToString();
  728. }
  729. if (e.TimeElapsed.ContainsKey(EnumProcessTime.OrganSegProcessTime))
  730. {
  731. organSegTime = e.TimeElapsed[EnumProcessTime.OrganSegProcessTime].ToString();
  732. }
  733. Dispatcher.Invoke(() =>
  734. {
  735. TextTestTotalTime.Text = totalTime;
  736. TextOrganSegTime.Text = organSegTime;
  737. });
  738. // 更新显示结果
  739. if (e.DetectedResult.SegResults != null)
  740. {
  741. MyImageCanvas.UpdateTestResults(e.DetectedResult);
  742. }
  743. else
  744. {
  745. MyImageCanvas.ClearTestResult();
  746. }
  747. if (e.Mask.ByteCount > 0)
  748. {
  749. var bitmap = RawImageShowUtils.RawImageToBitmap(e.Mask);
  750. Dispatcher.Invoke(() =>
  751. {
  752. UsImage.Source = RawImageShowUtils.BitmapToBitmapImage(bitmap);
  753. });
  754. }
  755. }
  756. }
  757. /// <summary>
  758. /// 有log要记
  759. /// </summary>
  760. /// <param name="sender"></param>
  761. /// <param name="e"></param>
  762. private void OnLogWrite(object sender, LogEventArgs e)
  763. {
  764. switch (e.LogType)
  765. {
  766. case EnumLogType.InfoLog:
  767. LogHelper.InfoLog(e.Msg, string.Empty);
  768. break;
  769. case EnumLogType.WarnLog:
  770. LogHelper.WarnLog(e.Msg, string.Empty);
  771. break;
  772. case EnumLogType.ErrorLog:
  773. LogHelper.ErrorLog(e.Msg, string.Empty);
  774. break;
  775. case EnumLogType.FatalLog:
  776. LogHelper.FatalLog(e.Msg, string.Empty);
  777. break;
  778. }
  779. }
  780. /// <summary>
  781. /// 有错误发生
  782. /// </summary>
  783. /// <param name="sender"></param>
  784. /// <param name="e"></param>
  785. private void OnErrorOccur(object sender, ErrorEventArgs e)
  786. {
  787. MessageBox.Show("发生错误:" + e.GetException());
  788. }
  789. #endregion
  790. /// <summary>
  791. /// 鼠标左键按下
  792. /// </summary>
  793. /// <param name="sender"></param>
  794. /// <param name="e"></param>
  795. private void Canvas_MouseLeftBtnDown(object sender, MouseButtonEventArgs e)
  796. {
  797. if (_isManulSelROI)
  798. {
  799. //清空原始图像上面的路径点
  800. _contourInOrigImg = new List<Point2D>();
  801. _drawingPoints = new List<System.Windows.Point>();
  802. System.Windows.Point mousePosInCanvas = e.GetPosition((IInputElement)sender);
  803. _mouseStartPos = mousePosInCanvas;
  804. _drawingPoints = new List<System.Windows.Point>();
  805. _drawingPoints.Add(mousePosInCanvas);
  806. _mouseLeftBtnPressed = true;
  807. }
  808. }
  809. /// <summary>
  810. /// 鼠标左键弹起
  811. /// </summary>
  812. /// <param name="sender"></param>
  813. /// <param name="e"></param>
  814. private void Canvas_MouseLeftBtnUp(object sender, MouseButtonEventArgs e)
  815. {
  816. if (_isManulSelROI)
  817. {
  818. _mouseLeftBtnPressed = false;
  819. System.Windows.Point mousePosInCanvas = e.GetPosition((IInputElement)sender);
  820. // 记录下在原图上面的起始点
  821. _mousePosInOrigImg = MyImageCanvas.TransBack(mousePosInCanvas);
  822. _startPosInOrigImg = MyImageCanvas.TransBack(_mouseStartPos);
  823. _contourInOrigImg.Add(_startPosInOrigImg);
  824. _contourInOrigImg.Add(_mousePosInOrigImg);
  825. // 更新显示
  826. int x = _startPosInOrigImg.X;
  827. int y = _startPosInOrigImg.Y;
  828. int w = _mousePosInOrigImg.X - _startPosInOrigImg.X;
  829. int h = _mousePosInOrigImg.Y - _startPosInOrigImg.Y;
  830. roisManual.Add(new Rect(x, y, w, h));
  831. RoiInfo rect = new RoiInfo(new Rect(x, y, w, h), System.Windows.Media.Brushes.Yellow);
  832. if (roisManual.Count == 1)
  833. {
  834. MyImageCanvas.DrawRoiInCanvas(rect, "liver");
  835. }
  836. else if (roisManual.Count == 2)
  837. {
  838. MyImageCanvas.DrawRoiInCanvas(rect, "kidney");
  839. }
  840. else
  841. {
  842. MyImageCanvas.RemoveRoiInCanvas("liver");
  843. MyImageCanvas.RemoveRoiInCanvas("kidney");
  844. roisManual.Clear();
  845. MessageBox.Show("选择超过两个框,清空重选!");
  846. }
  847. }
  848. }
  849. /// <summary>
  850. /// 鼠标移动
  851. /// </summary>
  852. /// <param name="sender"></param>
  853. /// <param name="e"></param>
  854. private void Canvas_MouseMove(object sender, MouseEventArgs e)
  855. {
  856. if (_isManulSelROI)
  857. {
  858. // 显示鼠标位置
  859. System.Windows.Point mousePosInCanvas = e.GetPosition((IInputElement)sender);
  860. //Point2D mousePosInOrigImg = MyImageCanvas.TransBack(mousePosInCanvas);
  861. // 判断鼠标当前状态
  862. if (e.LeftButton == MouseButtonState.Pressed)
  863. {
  864. }
  865. else
  866. {
  867. if (_mouseLeftBtnPressed)
  868. {
  869. Canvas_MouseLeftBtnUp(MyImageCanvas, new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left));
  870. }
  871. }
  872. }
  873. }
  874. }
  875. }