123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762 |
- using System;
- using System.IO;
- using System.Windows;
- using System.Drawing;
- using System.Threading;
- using Microsoft.Win32;
- using System.Windows.Threading;
- using System.Collections.Generic;
- using Accord.Video.FFMPEG;
- using AI.DiagSystem.Workers;
- using AI.DiagSystem.Workers.WorkerInputs;
- using ImageShowUtilsLib;
- using AI.Common;
- using AI.Common.Log;
- using AI.DiagSystem;
- namespace AIMultiInferWorkDemo
- {
- /// <summary>
- /// 图像相关信息
- /// </summary>
- public class ImageSourceFileInfo
- {
- private VideoFileReader _videoReader;
- public string OrigPath { get; protected set; }
- public bool IsVideo { get; protected set; }
- public int ImageCount { get; protected set; }
- public Bitmap GetOrigImage(int index = 0)
- {
- if (!File.Exists(OrigPath))
- {
- return null;
- }
- if (IsVideo)
- {
- if (index >= ImageCount)
- {
- return null;
- }
- var img = _videoReader.ReadVideoFrame(index);
- return img;
- }
- else
- {
- var img = new Bitmap(OrigPath);
- return img;
- }
- }
- public ImageSourceFileInfo(string origImagePath)
- {
- OrigPath = origImagePath;
- // 是否为视频
- FileInfo fileInfo = new FileInfo(origImagePath);
- IsVideo = false;
- if ((fileInfo.Extension == ".mp4") || (fileInfo.Extension == ".avi") || (fileInfo.Extension == ".wmv")
- || (fileInfo.Extension == ".MP4") || (fileInfo.Extension == ".AVI") || (fileInfo.Extension == ".WMV"))
- {
- IsVideo = true;
- }
- // 如果是视频,需要_videoReader打开它
- if (IsVideo)
- {
- _videoReader = new VideoFileReader();
- _videoReader.Open(origImagePath);
- if (_videoReader.CodecName == ".wmv2")
- {
- int count = 0;
- while (_videoReader.ReadVideoFrame(count) != null)
- {
- count += 1;
- }
- ImageCount = count;
- }
- else
- {
- ImageCount = (int)_videoReader.FrameCount;
- }
- }
- else
- {
- ImageCount = 1;
- }
- }
- public void Dispose()
- {
- if (_videoReader != null)
- {
- _videoReader.Close();
- _videoReader.Dispose();
- _videoReader = null;
- }
- }
- }
- /// <summary>
- /// MainWindow.xaml 的交互逻辑
- /// </summary>
- public partial class MainWindow : Window
- {
- #region private variables
- private WorkerManager _workManager = null;
- private AI.DiagSystem.ResultsAggregator _resultAggregator = null;
- private const int _numWorker = 2;
- private const int _modelCPU = 2;
- private const int _calCPU = 1;
- private const int _sleepTime = 500;
- private const bool _isCropped = false;
- private volatile bool _disposing = false;
- private volatile bool _loaded = false;
- private volatile EnumInferWorkName _inferWorkName1;
- private volatile EnumInferWorkName _inferWorkName2;
- private volatile ImageSourceFileInfo _imageSource1 = null;
- private volatile int _index1 = 0;
- private Thread _videoPlayThread1 = null;
- private volatile bool _videoPlaying1 = false;
- private volatile bool _stopVideoPlay1 = false;
- private volatile bool _reuse1 = false;
- private volatile bool _enableLesionSeg1 = false;
- private volatile bool _enableDescription1 = false;
- private volatile ImageSourceFileInfo _imageSource2 = null;
- private volatile int _index2 = 0;
- private Thread _videoPlayThread2 = null;
- private volatile bool _videoPlaying2 = false;
- private volatile bool _stopVideoPlay2 = false;
- private volatile bool _reuse2 = false;
- private volatile bool _enableLesionSeg2 = false;
- private volatile bool _enableDescription2 = false;
- private volatile bool _errorMsgShowing = false;
- #endregion
- #region 用户界面响应
- public MainWindow()
- {
- InitializeComponent();
- ComboBoxInferNames1.SelectionChanged -= OnInferNames1Changed;
- ComboBoxInferNames2.SelectionChanged -= OnInferNames2Changed;
- ComboBoxInferNames1.Items.Clear();
- ComboBoxInferNames2.Items.Clear();
- foreach (var inferName in Enum.GetValues(typeof(EnumInferWorkName)))
- {
- if ((EnumInferWorkName)inferName != EnumInferWorkName.Default &&
- (EnumInferWorkName)inferName != EnumInferWorkName.BreastDSOD &&
- (EnumInferWorkName)inferName != EnumInferWorkName.BreastDSOD_LiverYOLO &&
- (EnumInferWorkName)inferName != EnumInferWorkName.BreastDSOD_LiverKerasSeg &&
- (EnumInferWorkName)inferName != EnumInferWorkName.UserDefine2 &&
- (EnumInferWorkName)inferName != EnumInferWorkName.UserDefine3)
- {
- ComboBoxInferNames1.Items.Add(inferName);
- ComboBoxInferNames2.Items.Add(inferName);
- }
- }
- ComboBoxInferNames1.SelectionChanged += OnInferNames1Changed;
- ComboBoxInferNames2.SelectionChanged += OnInferNames2Changed;
- ComboBoxInferNames1.SelectedIndex = 0;
- ComboBoxInferNames2.SelectedIndex = 1;
- InitWorkManager();
- }
- private void OnBtnLoadImage1Click(object sender, RoutedEventArgs e)
- {
- if (!_loaded)
- {
- MessageBox.Show("请先加载模型.");
- return;
- }
- OpenFileDialog openFileDialog = new OpenFileDialog
- {
- Filter = "图片或视频|*.png;*.PNG;*.bmp;*.BMP;*.jpg;*.JPG;*.jpeg;*.JPEG;*.mp4;*.MP4;*.avi;*.AVI;*.wmv;*.WMV",
- Multiselect = false,
- Title = "选择一个图像或视频"
- };
- if (openFileDialog.ShowDialog() ?? false)
- {
- if (_imageSource1 != null)
- {
- if (_imageSource1.IsVideo && _videoPlaying1)
- {
- _stopVideoPlay1 = true;
- while (_videoPlaying1)
- {
- Thread.Sleep(5);
- }
- }
- _imageSource1.Dispose();
- }
- _imageSource1 = new ImageSourceFileInfo(openFileDialog.FileName);
- _index1 = 0;
- if (_imageSource1.IsVideo)
- {
- _videoPlaying1 = true;
- BtnStop1.Visibility = Visibility.Visible;
- BtnStop1.Content = "暂停";
- CheckBoxReuse1.Visibility = Visibility.Visible;
- if (_videoPlayThread1 == null || !_videoPlayThread1.IsAlive)
- {
- _videoPlayThread1 = new Thread(() => DoVideoPlay1())
- {
- IsBackground = true,
- Name = "AI_VideoPlay_1"
- };
- _videoPlayThread1.Start();
- }
- }
- else
- {
- BtnStop1.Visibility = Visibility.Hidden;
- CheckBoxReuse1.Visibility = Visibility.Hidden;
- TestOneFrame1();
- }
- }
- }
- private void OnBtnStop1Click(object sender, RoutedEventArgs e)
- {
- if (!_loaded)
- {
- MessageBox.Show("请先加载模型.");
- return;
- }
- if (_videoPlaying1)
- {
- BtnStop1.Content = "继续";
- _videoPlaying1 = false;
- }
- else
- {
- BtnStop1.Content = "暂停";
- _videoPlaying1 = true;
- if (_videoPlayThread1 == null || !_videoPlayThread1.IsAlive)
- {
- _videoPlayThread1 = new Thread(() => DoVideoPlay1())
- {
- IsBackground = true,
- Name = "AI_VideoPlay_1"
- };
- _videoPlayThread1.Start();
- }
- }
- }
- private void OnUncheckedReuse1(object sender, RoutedEventArgs e)
- {
- _reuse1 = false;
- }
- private void OnCheckedReuse1(object sender, RoutedEventArgs e)
- {
- _reuse1 = true;
- }
- private void OnUncheckedEnabelLesionSeg1(object sender, RoutedEventArgs e)
- {
- _enableLesionSeg1 = false;
- }
- private void OnCheckedEnableLesionSeg1(object sender, RoutedEventArgs e)
- {
- _enableLesionSeg1 = true;
- }
- private void OnUncheckedEnableDescription1(object sender, RoutedEventArgs e)
- {
- _enableDescription1 = false;
- }
-
- private void OnCheckedEnableDescription1(object sender, RoutedEventArgs e)
- {
- _enableDescription1 = true;
- }
- private void OnBtnLoadImage2Click(object sender, RoutedEventArgs e)
- {
- if (!_loaded)
- {
- MessageBox.Show("请先加载模型.");
- return;
- }
- OpenFileDialog openFileDialog = new OpenFileDialog
- {
- Filter = "图片或视频|*.png;*.PNG;*.bmp;*.BMP;*.jpg;*.JPG;*.jpeg;*.JPEG;*.mp4;*.MP4;*.avi;*.AVI;*.wmv;*.WMV",
- Multiselect = false,
- Title = "选择一个图像或视频"
- };
- if (openFileDialog.ShowDialog() ?? false)
- {
- if (_imageSource2 != null)
- {
- if (_imageSource2.IsVideo && _videoPlaying2)
- {
- _stopVideoPlay2 = true;
- while (_videoPlaying2)
- {
- Thread.Sleep(5);
- }
- }
- _imageSource2.Dispose();
- }
- _imageSource2 = new ImageSourceFileInfo(openFileDialog.FileName);
- _index2 = 0;
- if (_imageSource2.IsVideo)
- {
- _videoPlaying2 = true;
- BtnStop2.Visibility = Visibility.Visible;
- BtnStop2.Content = "暂停";
- CheckBoxReuse2.Visibility = Visibility.Visible;
- if (_videoPlayThread2 == null || !_videoPlayThread2.IsAlive)
- {
- _videoPlayThread2 = new Thread(() => DoVideoPlay2())
- {
- IsBackground = true,
- Name = "AI_VideoPlay_2"
- };
- _videoPlayThread2.Start();
- }
- }
- else
- {
- BtnStop2.Visibility = Visibility.Hidden;
- CheckBoxReuse2.Visibility = Visibility.Hidden;
- TestOneFrame2();
- }
- }
- }
- private void OnBtnStop2Click(object sender, RoutedEventArgs e)
- {
- if (!_loaded)
- {
- MessageBox.Show("请先加载模型.");
- return;
- }
- if (_videoPlaying2)
- {
- BtnStop2.Content = "继续";
- _videoPlaying2 = false;
- }
- else
- {
- BtnStop2.Content = "暂停";
- _videoPlaying2 = true;
- if (_videoPlayThread2 == null || !_videoPlayThread2.IsAlive)
- {
- _videoPlayThread2 = new Thread(() => DoVideoPlay2())
- {
- IsBackground = true,
- Name = "AI_VideoPlay_2"
- };
- _videoPlayThread2.Start();
- }
- }
- }
- private void OnUncheckedReuse2(object sender, RoutedEventArgs e)
- {
- _reuse2 = false;
- }
- private void OnCheckedReuse2(object sender, RoutedEventArgs e)
- {
- _reuse2 = true;
- }
- private void OnUncheckedEnabelLesionSeg2(object sender, RoutedEventArgs e)
- {
- _enableLesionSeg2 = false;
- }
- private void OnCheckedEnableLesionSeg2(object sender, RoutedEventArgs e)
- {
- _enableLesionSeg2 = true;
- }
- private void OnUncheckedEnableDescription2(object sender, RoutedEventArgs e)
- {
- _enableDescription2 = false;
- }
- private void OnCheckedEnableDescription2(object sender, RoutedEventArgs e)
- {
- _enableDescription2 = true;
- }
- private void OnInferNames1Changed(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
- {
- _loaded = false;
- _inferWorkName1 = (EnumInferWorkName)ComboBoxInferNames1.SelectedItem;
- }
- private void OnInferNames2Changed(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
- {
- _loaded = false;
- _inferWorkName2 = (EnumInferWorkName)ComboBoxInferNames2.SelectedItem;
- }
- private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
- {
- DoDispose();
- }
- private void OnBtnDisposeClick(object sender, RoutedEventArgs e)
- {
- DoDispose();
- }
- private void OnBtnLoadClick(object sender, RoutedEventArgs e)
- {
- InitWorkManager();
- }
- #endregion
- #region private
- /// <summary>
- /// 初始化workmanager
- /// </summary>
- private void InitWorkManager()
- {
- // 初始化workManager
- _workManager = new WorkerManager(25, _numWorker, _modelCPU, _calCPU, "",new List<EnumInferWorkName> { _inferWorkName1,_inferWorkName2});
- _workManager.NotifyInferFinish += OnWorkerInferFinish;
- _workManager.NotifyError += OnErrorOccur;
- _workManager.NotifyLog += OnLogWrite;
- // 初始化resultAggregator
- _resultAggregator = new AI.DiagSystem.ResultsAggregator(false, -1);
- _resultAggregator.NotifyLog += OnLogWrite;
- _loaded = true;
- _disposing = false;
- _stopVideoPlay1 = false;
- _stopVideoPlay2 = false;
- }
- /// <summary>
- /// 收到workManager的推理结束通知
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void OnWorkerInferFinish(object sender, InferFinishEventArgs e)
- {
- if (!_disposing)
- {
- _resultAggregator.AddInferResult(e.WorkerResult);
- UpdateInferTime(e.TimeElapsed, e.InferSize);
- }
- }
- /// <summary>
- /// 收到发生错误的通知
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void OnErrorOccur(object sender, ErrorEventArgs e)
- {
- if (!_errorMsgShowing)
- {
- Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
- {
- _errorMsgShowing = true;
- MessageBox.Show("推理过程中发生错误!" + e.GetException());
- _errorMsgShowing = false;
- }));
- }
- }
- /// <summary>
- /// 有log要记
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="e"></param>
- private void OnLogWrite(object sender, LogEventArgs e)
- {
- Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
- {
- TextLog.Text += e.Msg +"\r\n";
- }));
- }
- /// <summary>
- /// 播放视频1
- /// </summary>
- private void DoVideoPlay1()
- {
- while (!_disposing)
- {
- if (_stopVideoPlay1)
- {
- _videoPlaying1 = false;
- _stopVideoPlay1 = false;
- }
- else
- {
- if (_videoPlaying1 && _imageSource1 != null)
- {
- if (!_imageSource1.IsVideo)
- {
- Thread.Sleep(5);
- continue;
- }
- if (_index1 <= -1)
- {
- Thread.Sleep(5);
- continue;
- }
- TestOneFrame1();
- Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
- {
- ProgressBar1.Value = (int)((double)_index1 / _imageSource1.ImageCount * 100);
- }));
- // 更新index
- if (_index1 < _imageSource1.ImageCount - 1)
- {
- _index1 += 1;
- }
- else
- {
- if (_reuse1)
- {
- _index1 = 0;
- }
- else
- {
- _index1 = -1;
- }
- }
- Thread.Sleep(_sleepTime);
- }
- else
- {
- Thread.Sleep(5);
- }
- }
- }
- _videoPlaying1 = false;
- }
- /// <summary>
- /// 播放视频2
- /// </summary>
- private void DoVideoPlay2()
- {
- while (!_disposing)
- {
- if (_stopVideoPlay2)
- {
- _videoPlaying2 = false;
- _stopVideoPlay2 = false;
- }
- else
- {
- if (_videoPlaying2 && _imageSource2 != null)
- {
- if (!_imageSource2.IsVideo)
- {
- Thread.Sleep(5);
- continue;
- }
- if (_index2 <= -1)
- {
- Thread.Sleep(5);
- continue;
- }
- TestOneFrame2();
- Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
- {
- ProgressBar2.Value = (int)((double)_index2 / _imageSource2.ImageCount * 100);
- }));
- // 更新index
- if (_index2 < _imageSource2.ImageCount - 1)
- {
- _index2 += 1;
- }
- else
- {
- if (_reuse2)
- {
- _index2 = 0;
- }
- else
- {
- _index2 = -1;
- }
- }
- Thread.Sleep(_sleepTime);
- }
- else
- {
- Thread.Sleep(5);
- }
- }
- }
- _videoPlaying2 = false;
- }
- /// <summary>
- /// 评估单幅图像
- /// 推理请求被塞入待处理队列后,等待诊断系统给出结果后再返回
- /// </summary>
- /// <param name="image"></param>
- /// <param name="isCropped"></param>
- /// <param name="scanPart"></param>
- /// <returns></returns>
- private AIDiagResultPerImg EvaluateOneImage(RawImage image, bool isCropped, bool enableLesionSeg, bool enableDescription, EnumScanParts scanPart, EnumInferWorkName inferTaskName)
- {
- // 生成随机码,作为diagId和inferId
- string diagId = Guid.NewGuid().ToString();
- WorkerInputBatchImages input = new WorkerInputBatchImages(diagId, diagId,
- new RawImage(image.DataBuffer, image.Width, image.Height, image.ColorType),
- isCropped,enableLesionSeg, enableDescription, scanPart,inferTaskName);
- _workManager.AddInferRequest(input);
- // 将相关信息塞入结果收集器
- _resultAggregator.AddNewDiag(diagId, 1, isCropped,enableLesionSeg, enableDescription,scanPart, inferTaskName);
- _resultAggregator.AddNewInfer(diagId, diagId, 1);
- // 等待结果
- AI.DiagSystem.AIDiagResultPerImg result = null;
- bool waiting = true;
- while (waiting && !_disposing)
- {
- if (!_resultAggregator.GetIsFinish(diagId))
- {
- Thread.Sleep(5);
- }
- else
- {
- waiting = false;
- var ret = (AI.DiagSystem.AIDiagResultBatchImages)_resultAggregator.GetDiagResults(diagId);
- result = ret.DiagResult[0];
- }
- }
- return result;
- }
- /// <summary>
- /// 将结果画到图上
- /// </summary>
- /// <param name="image"></param>
- /// <param name="diagResult"></param>
- /// <param name="inferWorkName"></param>
- private void DrawResultOnImage(Bitmap image, AI.DiagSystem.AIDiagResultPerImg diagResult)
- {
- try
- {
- ResultShowGrid.UpdateImage(image);
- ResultShowGrid.UpdateDiagResult(diagResult);
- }
- catch (Exception excep)
- {
- MessageBox.Show("出错了:" + excep);
- }
- }
- /// <summary>
- /// 将推理耗时显示到界面上
- /// </summary>
- /// <param name="inferTime"></param>
- private void UpdateInferTime(Dictionary<string, int> inferTime, int inferSize)
- {
- string inferTimePerTask = "";
- foreach (var taskname in inferTime.Keys)
- {
- inferTimePerTask += "{'" + taskname + "':" + inferTime[taskname].ToString() + "}\r\n";
- }
- string inferTimeStr = "InferSize:" + inferSize + ",\r\nInferTimePerTask:\r\n" + inferTimePerTask;
- Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
- {
- TextInferTime.Text = inferTimeStr;
- }));
- }
- private void DoDispose()
- {
- try
- {
- _disposing = true;
- _stopVideoPlay1 = true;
- while (_videoPlaying1)
- {
- Thread.Sleep(5);
- }
- _imageSource1?.Dispose();
- _stopVideoPlay2 = true;
- while (_videoPlaying2)
- {
- Thread.Sleep(5);
- }
- _imageSource2?.Dispose();
- _workManager?.Dispose();
- _resultAggregator?.Dispose();
- _loaded = false;
- }
- catch (Exception excep)
- {
- MessageBox.Show("释放时出错:" + excep);
- }
- }
- private void TestOneFrame1()
- {
- // 取出当前图像
- Bitmap image = _imageSource1.GetOrigImage(_index1);
- // 测试
- var rawImg = RawImageShowUtils.BitmapToRawImage(image);
- RawImage rawImage = new RawImage(rawImg.DataBuffer, rawImg.Width, rawImg.Height, rawImg.ColorType);
- EnumInferWorkName inferWorkName = _inferWorkName1;
- var result = EvaluateOneImage(rawImage, _isCropped, _enableLesionSeg1, _enableDescription1, EnumScanParts.NotSpecified, inferWorkName);
- rawImage.Dispose();
- rawImg.Dispose();
- if (result == null)
- {
- image.Dispose();
- return;
- }
- // 更新显示
- DrawResultOnImage(image, result);
- image.Dispose();
- }
- private void TestOneFrame2()
- {
- // 取出当前图像
- Bitmap image = _imageSource2.GetOrigImage(_index2);
- // 测试
- var rawImg = RawImageShowUtils.BitmapToRawImage(image);
- RawImage rawImage = new RawImage(rawImg.DataBuffer, rawImg.Width, rawImg.Height, rawImg.ColorType);
- EnumInferWorkName inferWorkName = _inferWorkName2;
- var result = EvaluateOneImage(rawImage, _isCropped, _enableLesionSeg2, _enableDescription2, EnumScanParts.NotSpecified, inferWorkName);
- rawImage.Dispose();
- rawImg.Dispose();
- if (result == null)
- {
- image.Dispose();
- return;
- }
- // 更新显示
- DrawResultOnImage(image, result);
- image.Dispose();
- }
- #endregion
- }
- }
|