using System; using System.IO; using System.Text; using System.Collections.Generic; using System.Windows; using System.Windows.Shapes; using System.Windows.Input; using System.Drawing; using System.Data.SQLite; using Newtonsoft.Json; using System.Security.Cryptography; using System.Windows.Media.Imaging; using System.Windows.Controls; using System.Drawing.Imaging; using System.Windows.Threading; using Microsoft.Win32; using AI.Common.Interface; using RawImageShowUtilsLib; using AIModuleResultShowUtilsLib; using System.Xml.Linq; using AI.Common.Implements; using static System.Windows.Forms.AxHost; using System.Security.Policy; using System.Windows.Media; using System.ComponentModel; using System.Windows.Forms; namespace AILesionDescriptionGTGenerator { /// /// Canvas上绘制的目标有几种类型 /// public enum EnumCanvasItemType { Drawing, Choosed, Existed, } /// /// 线的种类 /// public enum EnumCanvasLineType { Horizontal, Vertical, } /// /// 鼠标状态 /// public enum EnumMouseOperType { None, DrawingContour, DrawingHorizonLines, DrawingVerticalLines, DrawingPoint, } public enum EnumDesShapeValue { /// /// 椭圆形 /// Oval, /// /// 类圆形 /// Round, /// /// 不规则形 /// Irregular, } /// /// 方向描述可能的结果值 /// public enum EnumDesOrientationValue { /// /// 平行 /// Parallel, /// /// 非平行 /// NonParallel, } /// /// 内部回声描述可能的结果 /// public enum EnumDesEchoPatternValue { /// /// 无回声 /// Anechoic, /// /// 低回声 /// Hypoechoic, /// /// 等回声 /// Isoechoic, /// /// 高回声 /// Hyperechoic, /// /// 混合回声 /// Complex, /// /// 强回声 /// Strongechoic, } /// /// 病灶边界描述可能的结果 /// public enum EnumDesLesionBoundaryValue { /// /// 清晰 /// AbruptInterface, /// /// 模糊 /// EchogenicHalo, } /// /// 病灶边缘描述的可能结果 /// public enum EnumDesMarginValue { /// /// 光整 /// Circumscribed, /// /// 不光整 /// NonCircumscribed, } /// /// 病灶信息 /// public class LesionInfo { /// /// 病灶轮廓 /// public List Contour { get; set; } = new List(); /// /// 病灶形状 /// public EnumDesShapeValue Shape { get; set; } = EnumDesShapeValue.Oval; /// /// 方向 /// public EnumDesOrientationValue Orientation { get; set; } = EnumDesOrientationValue.Parallel; /// /// 回声类型 /// public EnumDesEchoPatternValue EchoPattern { get; set; } = EnumDesEchoPatternValue.Hypoechoic; /// /// 边界清晰不清晰 /// public EnumDesLesionBoundaryValue Boundary { get; set; } = EnumDesLesionBoundaryValue.AbruptInterface; /// /// 边缘光整不光整 /// public EnumDesMarginValue Margin { get; set; } = EnumDesMarginValue.Circumscribed; /// /// 横径起点 /// public Point2D HorizontalPoint1 { get; set; } = new Point2D(); /// /// 横径终点 /// public Point2D HorizontalPoint2 { get; set; } = new Point2D(); /// /// 纵径起点 /// public Point2D VerticalPoint1 { get; set; } = new Point2D(); /// /// 纵径终点 /// public Point2D VerticalPoint2 { get; set; } = new Point2D(); /// /// 内容完整 /// public bool IsCompleted { get { return Contour.Count > 0 && HorizontalPoint1 != HorizontalPoint2 && VerticalPoint1 != VerticalPoint2; } } } /// /// 病灶描述GT图像信息 /// public class LesionDesGTImgInfo { public string ImageId { get; set; } /// /// 病灶分级 /// public List Label { get; set; } /// /// 该图上所有病灶的标准描述 /// public List Lesions { get; set; } } /// /// MainWindow.xaml 的交互逻辑 /// public partial class MainWindow : Window { #region private variables private readonly string _dataFolder = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.IO.Path.GetDirectoryName( AppDomain.CurrentDomain.BaseDirectory)),"LesionDescriptionGTDatas"); private readonly string _dbPath; private readonly string _imageDataFolder; private readonly string _dbModelPath; private List _allImages = new List(); private volatile int _imgIndex = 0; private List _lesions = new List(); private volatile int _lesionIndex = 0; private volatile bool _modified = false; private BitmapImage _origimg = null; private BitmapImage _drawimg = null; // 鼠标动作 private volatile EnumMouseOperType _mouseOper = EnumMouseOperType.None; private volatile bool _mouseLeftBtnPressed = false; // 鼠标绘制的起始位置(画横轴,纵轴时需要) private System.Windows.Point _mouseStartPos; // 绘制中的所有轮廓点的集合 private List _drawingPoints = new List(); private volatile bool _canAutoFinish = false; //private DataBase _creatBd = new DataBase(); private Bitmap _image = null; private BitmapImage _dstImgWin = null; private LesionDesGTImgInfo _modelResult = new LesionDesGTImgInfo(); //模型检测出的病灶结果 private volatile bool _showModelResult = false; private volatile int _lesionOriModelIndex = 0;//左侧界面病灶ID private List _lesionsLabels = new List(); //private List _lesionsModelLabels = new List(); private volatile int _lesionLabelIndex = 0; private volatile bool _showDrawingResult = false; private volatile int _num = 0; private IModule _module; private string _currentPath; private InferenceConfig _inferConfig = new InferenceConfig(); private string _netDir = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Networks"); private volatile string _processId = string.Empty; private volatile string _caseId = string.Empty; private volatile string _dataId = string.Empty; private volatile bool _readingVideo; private volatile int _frameIndex; IDetectedObject[] _newModelResult; //回声 private int _Anechoic_Anechoic_num = 0; //无回声 判为 无回声 的数目 private int _Anechoic_Hypoechoic_num = 0; //无回声 判为 低回声 的数目 private int _Anechoic_Isoechoic_num = 0; //无回声 判为 等回声 的数目 private int _Anechoic_Hyperechoic_num = 0; //无回声 判为 高回声 的数目 private int _Anechoic_Complex_num = 0; //无回声 判为 Complex 的数目 private int _Hyperechoic_Hyperechoic_num = 0; //高回声 判为 高回声 private int _Hyperechoic_Anechoic_num = 0; private int _Hyperechoic_Isoechoic_num = 0; private int _Hyperechoic_Hypoechoic_num = 0; private int _Hyperechoic_Complex_num = 0; private int _Isoechoic_Isoechoic_num = 0; //等回声 判为 等回声 private int _Isoechoic_Anechoic_num = 0; private int _Isoechoic_Hyperechoic_num = 0; private int _Isoechoic_Hypoechoic_num = 0; private int _Isoechoic_Complex_num = 0; private int _Hypoechoic_Hypoechoic_num = 0; //低回声 判为 低回声 private int _Hypoechoic_Anechoic_num = 0; private int _Hypoechoic_Hyperechoic_num = 0; private int _Hypoechoic_Isoechoic_num = 0; private int _Hypoechoic_Complex_num = 0; private int _Complex_Complex_num = 0; //极低回声 判为 极低回声 private int _Complex_Anechoic_num = 0; private int _Complex_Hyperechoic_num = 0; private int _Complex_Isoechoic_num = 0; private int _Complex_Hypoechoic_num = 0; //形状 private int _Oval_Oval_num = 0; //椭圆形 判为 椭圆形 private int _Oval_Round_num = 0; //椭圆形 判为 类圆形 private int _Oval_Irregular_num = 0; //椭圆形 判为 不规则形 private int _Round_Round_num = 0; //类圆形 判为 类圆形 private int _Round_Oval_num = 0; //类圆形 判为 椭圆形 private int _Round_Irregular_num = 0; //类圆形 判为 不规则形 private int _Irregular_Irregular_num = 0; //不规则形 判为 不规则形 private int _Irregular_Oval_num = 0; //不规则形 判为 椭圆形 private int _Irregular_Round_num = 0; //不规则形 判为 类圆形 //边缘 private int _Circumscribed_Circumscribed_num = 0; //光整 判为 不光整 private int _Circumscribed_NonCircumscribed_num = 0; private int _NonCircumscribed_NonCircumscribed_num = 0; //不光整 判为 光整 private int _NonCircumscribed_Circumscribed_num = 0; //边界 private int _AbruptInterface_AbruptInterface_num; //清晰--清晰 private int _AbruptInterface_EchogenicHalo_num; //清晰--模糊 private int _EchogenicHalo_EchogenicHalo_num; //模糊--模糊 private int _EchogenicHalo_AbruptInterface_num; //模糊--清晰 //方向 private int _Parallel_Parallel_num; //平行--平行 private int _Parallel_NonParallel_num; //平行--非平行 private int _NonParallel_NonParallel_num; //非平行--非平行 private int _NonParallel_Parallel_num; //非平行--平行 #endregion #region 用户界面响应 public MainWindow() { InitializeComponent(); InitializeComboBoxLesionsLabel(); _dbPath = System.IO.Path.Combine(_dataFolder, "lesion_des_gt_datas.db"); _imageDataFolder = System.IO.Path.Combine(_dataFolder, "Images"); _currentPath = System.Environment.CurrentDirectory; _module = new AI.Vaid.Modules.BreastLesionDetect.BreastLesionDetect(_netDir, _inferConfig, EnumDeviceType.CPU); bool existDb = CreateDataBase(); if(existDb) { AddNewImages(_imageDataFolder); } UserControlLesionSelected.NotifyLesionInfoEventArgs += OnLesionInfoSelectorEventOccur; ReadDataBase(); DrawImage.Source = _drawimg; OrigImage.Source = _origimg; DetectImage(_image); } /// /// 点击 "前一幅图" /// /// /// private void OnBtnPreviousImageClicked(object sender, RoutedEventArgs e) { // 查看当前图的ROI是否已经绘制完毕 if (_lesions.Count > 0) { if (_lesions.Count != _lesionsLabels.Count) { System.Windows.MessageBox.Show("请先将当前图像的描述添加完整,或删除不需要的描述后再查看新的图像"); return; } foreach (var lesion in _lesions) { if (!lesion.IsCompleted) { System.Windows.MessageBox.Show("请先将当前图像的描述添加完整,或删除不需要的描述后再查看新的图像"); return; } } for (int i = 0; i < _lesionsLabels.Count; i++)//add { //if (_lesionsLabels[i] < 1) //{ // string str = "请先将当前图像的描述的第:" + i.ToString() + "个病灶等级添加完整"; // MessageBox.Show(str); // return; //} } } // 保存当前图的结果 if (_modified) { SetLesions(_allImages[_imgIndex].ImageId, _lesions); SetLesionsLabels(_allImages[_imgIndex].ImageId, _lesionsLabels); } // 如果已经OK,则更新记录 if (_imgIndex <= 0) { System.Windows.MessageBox.Show("已是第一个"); return; } _imgIndex = _imgIndex - 1; _dstImgWin = null; _modelResult = null; _modelResult = new LesionDesGTImgInfo(); CurrentImgIndexUpdated(); _drawingPoints.Clear();// _lesionOriModelIndex = 0; DetectImage(_image); } /// /// 点击 "后一幅图" /// /// /// private void OnBtnNextImageClicked(object sender, RoutedEventArgs e) { // 查看当前图像的ROI是否已经绘制完毕 if (_lesions.Count > 0) { if (_lesions.Count != _lesionsLabels.Count) { System.Windows.MessageBox.Show("请先将当前图像的描述添加完整,或删除不需要的描述后再查看新的图像"); return; } foreach (var lesion in _lesions) { if (!lesion.IsCompleted) { System.Windows.MessageBox.Show("请先将当前图像的描述添加完整,或删除不需要的描述后再查看新的图像"); return; } } for(int i =0; i < _lesionsLabels.Count; i++)//add { //if (_lesionsLabels[i] <1) //{ // string str = "请先将当前图像的描述的第:" + i.ToString() + "个病灶等级添加完整"; // MessageBox.Show(str); // return; //} } } // 保存当前图的结果 if (_modified) { SetLesions(_allImages[_imgIndex].ImageId, _lesions); SetLesionsLabels(_allImages[_imgIndex].ImageId, _lesionsLabels); } // 如果已经OK,则更新记录 if (_imgIndex >= _allImages.Count - 1) { System.Windows.MessageBox.Show("已是最后一个"); return; } _imgIndex = _imgIndex + 1; _dstImgWin = null; _modelResult = null; _modelResult = new LesionDesGTImgInfo(); CurrentImgIndexUpdated(); _drawingPoints.Clear();// _lesionOriModelIndex = 0; DetectImage(_image); } /// /// 选中的病灶改变 /// /// /// private void OnLesionSelectionChanged(object sender, SelectionChangedEventArgs e) { _lesionIndex = ComboBoxLesions.SelectedIndex; //_lesionIndex = 0;//add ??? LesionsUpdated(); } /// /// 删除选中的病灶 /// /// /// private void OnBtnDeleteSelROIClicked(object sender, RoutedEventArgs e) { if (_lesionIndex < 0) { System.Windows.MessageBox.Show("请先选择一个待删除的病灶"); return; } // 先清空画布上旧的显示内容 for (int ni = 0; ni < _lesions.Count; ni++) { RemoveContourInCanvas(ni.ToString()); RemoveLineInCanvas(EnumCanvasLineType.Horizontal, ni.ToString()); RemoveLineInCanvas(EnumCanvasLineType.Vertical, ni.ToString()); } _lesions.RemoveAt(_lesionIndex); _lesionsLabels.RemoveAt(_lesionIndex); _modified = true; if (_lesionIndex >= _lesions.Count) { if (_lesions.Count > 0) { _lesionIndex = 0; } else { _lesionIndex = -1; } } _drawingPoints.Clear(); LesionsUpdated(); } /// /// 新增病灶 /// /// /// private void OnBtnAddNewROIClicked(object sender, RoutedEventArgs e) { if (!UserControlLesionSelected.IsEmpty) { if (!UserControlLesionSelected.Lesion.IsCompleted) { System.Windows.MessageBox.Show("请先将现有病灶的描述添加完整后再增加新的病灶"); return; } if(_lesionLabelIndex < 1) { System.Windows.MessageBox.Show("请先将当前病灶等级添加完整"); return; } } _lesionIndex = _lesions.Count; _lesions.Add(new LesionInfo()); _lesionsLabels.Add(-1); _modified = true; _drawingPoints.Clear(); LesionsUpdated(); } /// /// 画布尺寸改变 /// /// /// private void Canvas_SizeChanged(object sender, SizeChangedEventArgs e) { MyCanvasDraw.Width = GridDrawImg.ActualWidth; MyCanvasDraw.Height = GridDrawImg.ActualHeight; ImageUpdated(); UpdateLesionsInCanvas(); UpdateLesionsIndex(); } /// /// 鼠标左键按下 /// /// /// private void Canvas_MouseLeftBtnDown(object sender, MouseButtonEventArgs e) { System.Windows.Point mousePosInCanvas = e.GetPosition((IInputElement)sender); _mouseStartPos = mousePosInCanvas; ////////////////// if (_drawingPoints.Count <= 0) { _drawingPoints = new List(); } else { } //var dd = _mouseOper; if (_mouseOper == EnumMouseOperType.DrawingPoint) { _drawingPoints.Add(mousePosInCanvas); } else if(_mouseOper == EnumMouseOperType.None) { _canAutoFinish = false; //_drawingPoints.Add(mousePosInCanvas); } else { _canAutoFinish = false; _drawingPoints.Add(mousePosInCanvas); } //_drawingPoints = new List(); //_canAutoFinish = false; //_drawingPoints.Add(mousePosInCanvas); _mouseLeftBtnPressed = true; } /// /// 鼠标左键弹起 /// /// /// private void Canvas_MouseLeftBtnUp(object sender, MouseButtonEventArgs e) { _mouseLeftBtnPressed = false; System.Windows.Point mousePosInCanvas = e.GetPosition((IInputElement)sender); Point2D mousePosInOrigImg = GetPosInOrigImage(mousePosInCanvas); Point2D startPosInOrigImg = GetPosInOrigImage(_mouseStartPos); switch (_mouseOper) { case EnumMouseOperType.DrawingContour: // 如果现在绘制的轮廓还未结束,就直接连接起点终点,将现在绘制的轮廓线,转换成图像坐标,发送给LesionInfoSelector,_mouseOper重置成空 if (_drawingPoints[_drawingPoints.Count - 1] != _drawingPoints[0]) { _drawingPoints.Add(_drawingPoints[0]); } List contourInOrigImg = new List(); foreach (var point in _drawingPoints) { contourInOrigImg.Add(GetPosInOrigImage(point)); } _drawingPoints = new List(); _mouseOper = EnumMouseOperType.None; RemoveContourInCanvas("drawing"); UserControlLesionSelected.SetContour(contourInOrigImg); //_canAutoFinish = false; break; case EnumMouseOperType.DrawingPoint: //if (_drawingPoints[_drawingPoints.Count - 1] != _drawingPoints[0]) { //_drawingPoints.Add(_drawingPoints[0]); DrawContourInCanvas(_drawingPoints, EnumCanvasItemType.Drawing, "drawingPt"); // 如果已经很靠近起始点,就自动结束 if (PointDistance(_drawingPoints[_drawingPoints.Count - 1], _drawingPoints[0]) < 5) { if (_canAutoFinish) { _drawingPoints.Add(_drawingPoints[0]); List contourInOrigImgPt = new List(); foreach (var point in _drawingPoints) { contourInOrigImgPt.Add(GetPosInOrigImage(point)); } _drawingPoints = new List(); _mouseOper = EnumMouseOperType.None; RemoveContourInCanvas("drawingPt"); UserControlLesionSelected.SetContour(contourInOrigImgPt); //_canAutoFinish = false; } } else { if (!_canAutoFinish) { _canAutoFinish = true; } } } break; case EnumMouseOperType.DrawingHorizonLines: // 将当前绘制的横径起点终点,转换成图像坐标,发送给LesionInfoSelector,_mouseOper重置成空 _mouseOper = EnumMouseOperType.None; RemoveLineInCanvas(EnumCanvasLineType.Horizontal,"drawing"); UserControlLesionSelected.SetHorizontalAxis(startPosInOrigImg, mousePosInOrigImg); break; case EnumMouseOperType.DrawingVerticalLines: // 将当前绘制的纵径起点终点,转换成图像坐标,发送给LesionInfoSelector,_mouseOper重置成空 _mouseOper = EnumMouseOperType.None; RemoveLineInCanvas(EnumCanvasLineType.Vertical, "drawing"); UserControlLesionSelected.SetVerticalAxis(startPosInOrigImg, mousePosInOrigImg); break; } } /// /// 鼠标移动 /// /// /// private void Canvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e) { // 显示鼠标位置 System.Windows.Point mousePosInCanvas = e.GetPosition((IInputElement)sender); Point2D mousePosInOrigImg = GetPosInOrigImage(mousePosInCanvas); TextBlockMousePosition.Text = mousePosInOrigImg.X.ToString() + "," + mousePosInOrigImg.Y.ToString(); // 判断鼠标当前状态 if (e.LeftButton == MouseButtonState.Pressed) { switch (_mouseOper) { case EnumMouseOperType.DrawingContour: _drawingPoints.Add(mousePosInCanvas); // 如果该图选中病灶已经有描述了,先清除Canvas上显示的,以免影响标注 if(_lesions[_lesionIndex].Contour.Count > 0) { RemoveContourInCanvas(_lesionIndex.ToString()); } // 更新显示正在绘制的轮廓线 DrawContourInCanvas(_drawingPoints, EnumCanvasItemType.Drawing, "drawing"); // 如果已经很靠近起始点,就自动结束 if (PointDistance(_drawingPoints[_drawingPoints.Count - 1], _drawingPoints[0]) < 5) { if (_canAutoFinish) { _drawingPoints.Add(_drawingPoints[0]); List contourInOrigImg = new List(); foreach (var point in _drawingPoints) { contourInOrigImg.Add(GetPosInOrigImage(point)); } _drawingPoints = new List(); _mouseOper = EnumMouseOperType.None; RemoveContourInCanvas("drawing"); UserControlLesionSelected.SetContour(contourInOrigImg); } } else { if (!_canAutoFinish) { _canAutoFinish = true; } } break; case EnumMouseOperType.DrawingPoint: //_drawingPoints.Add(mousePosInCanvas); //DrawContourInCanvas(_drawingPoints, EnumCanvasItemType.Drawing, "drawing"); break; case EnumMouseOperType.DrawingHorizonLines: // 如果该图选中病灶已经有横轴了,先清除Canvas上显示的,以免影响标注 RemoveLineInCanvas(EnumCanvasLineType.Horizontal, _lesionIndex.ToString()); // 更新显示正在绘制的横轴 DrawLineInCanvas(_mouseStartPos, mousePosInCanvas, EnumCanvasLineType.Horizontal, EnumCanvasItemType.Drawing, "drawing"); break; case EnumMouseOperType.DrawingVerticalLines: // 如果该图选中病灶已经有纵轴了,先清除Canvas上显示的,以免影响标注 RemoveLineInCanvas(EnumCanvasLineType.Vertical, _lesionIndex.ToString()); // 更新显示正在绘制的纵轴 DrawLineInCanvas(_mouseStartPos, mousePosInCanvas, EnumCanvasLineType.Vertical, EnumCanvasItemType.Drawing, "drawing"); break; } } else { if (_mouseLeftBtnPressed) { Canvas_MouseLeftBtnUp(MyCanvasDraw, new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, MouseButton.Left)); } } } #endregion #region public funcs /// /// 设置该图像的病灶 /// /// /// public void SetLesions(string imgId, List lesions) { try { SQLiteConnection dbCon = new SQLiteConnection("Data Source=" + _dbPath); dbCon.Open(); SQLiteCommand dbCmd; dbCmd = dbCon.CreateCommand(); string strLesions = JsonConvert.SerializeObject(lesions); dbCmd.CommandText = "update LesionDesGTDatas set Lesions='" + strLesions + "' where ImageId='" + imgId + "'"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); SQLiteDataReader dbreader; dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "select * from LastModification"; dbreader = dbCmd.ExecuteReader(); if (dbreader.HasRows) { dbreader.Close(); dbCmd.Dispose(); // 更新 dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "update LastModification set ImageId='" + imgId + "'"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); } else { // 新增 dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "insert into LastModification(ImageId) select '" + imgId + "'"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); } dbCon.Close(); dbCon.Dispose(); } catch (Exception excep) { System.Windows.MessageBox.Show("保存结果时出错!" + excep); } } /// /// 保存label /// /// /// public void SetLesionsLabels(string imgId, List lesionsLabels) { try { SQLiteConnection dbCon = new SQLiteConnection("Data Source=" + _dbPath); dbCon.Open(); SQLiteCommand dbCmd; dbCmd = dbCon.CreateCommand(); string strLesionsLabel = JsonConvert.SerializeObject(lesionsLabels); dbCmd.CommandText = "update LesionDesGTDatas set Label='" + strLesionsLabel + "' where ImageId='" + imgId + "'"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); SQLiteDataReader dbreader; dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "select * from LastModification"; dbreader = dbCmd.ExecuteReader(); if (dbreader.HasRows) { dbreader.Close(); dbCmd.Dispose(); // 更新 dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "update LastModification set ImageId='" + imgId + "'"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); } else { // 新增 dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "insert into LastModification(ImageId) select '" + imgId + "'"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); } dbCon.Close(); dbCon.Dispose(); } catch (Exception excep) { System.Windows.MessageBox.Show("保存病灶分级时出错!" + excep); } } #endregion #region private funcs private string ComputeHashCode(byte[] input) { MD5 md5 = MD5.Create(); byte[] hash = md5.ComputeHash(input); StringBuilder sb = new StringBuilder(); foreach (var b in hash) { sb.Append(b.ToString("x2")); } string hashstr = sb.ToString(); sb.Clear(); return hashstr; } /// /// 读入数据库 /// private void ReadDataBase() { try { if (!File.Exists(_dbPath)) { System.Windows.MessageBox.Show("未找到存放待标注数据的文件:" + _dbPath); return; } SQLiteConnection dbCon = new SQLiteConnection("Data Source=" + _dbPath); dbCon.Open(); SQLiteCommand dbCmd; dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "select * from LesionDesGTDatas"; SQLiteDataReader dbReader; dbReader = dbCmd.ExecuteReader(); if (!dbReader.HasRows) { dbReader.Close(); dbCmd.Dispose(); dbCon.Close(); dbCon.Dispose(); System.Windows.MessageBox.Show("待标注的数据为空."); return; } int index = 0; while (dbReader.Read()) { string imgId = ((string)dbReader[0]).TrimEnd(); string strLesions = ((string)dbReader[1]).TrimEnd(); List lesions = JsonConvert.DeserializeObject>(strLesions); string strLesionsLabels = ((string)dbReader[2]).TrimEnd(); List lesionsLabels = JsonConvert.DeserializeObject>(strLesionsLabels); index += 1; _allImages.Add(new LesionDesGTImgInfo { ImageId = imgId, Lesions = lesions , Label = lesionsLabels }); } dbReader.Close(); dbCmd.Dispose(); dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "select * from LastModification"; dbReader = dbCmd.ExecuteReader(); if (!dbReader.HasRows) { _imgIndex = 0; } else { dbReader.Read(); string imgId = ((string)dbReader[0]).TrimEnd(); int imgIndex = _allImages.FindIndex(x => x.ImageId == imgId); if (imgIndex == -1) { _imgIndex = 0; } else { _imgIndex = imgIndex; } } dbReader.Close(); dbCmd.Dispose(); dbCon.Close(); dbCon.Dispose(); if (_allImages.Count > 0) { CurrentImgIndexUpdated(); } } catch (Exception excep) { System.Windows.MessageBox.Show("读入数据库时出错:" + excep); } } /// /// 更新画布上显示的图像 /// private void ImageUpdated() { if (null == _drawimg) { return; } if (null == _origimg) { return; } // 计算缩放比例 double ratioW = GridDrawImg.ActualWidth / _drawimg.Width; double ratioH = GridDrawImg.ActualHeight / _drawimg.Height; double ratio = ratioW < ratioH ? ratioW : ratioH; DrawImgScaleTramsform.CenterX = 0; DrawImgScaleTramsform.CenterY = 0; DrawImgScaleTramsform.ScaleX = ratio; DrawImgScaleTramsform.ScaleY = ratio; OrigImgScaleTramsform.CenterX = 0; OrigImgScaleTramsform.CenterY = 0; OrigImgScaleTramsform.ScaleX = ratio; OrigImgScaleTramsform.ScaleY = ratio; // 使图像居中,需要平移 double translateX = 0; double translateY = 0; if (Math.Abs(ratio - ratioW) < 0.0001) { translateY = 0.5 * (ratioH - ratio) * _drawimg.Height; } else { translateX = 0.5 * (ratioW - ratio) * _drawimg.Width; } // 更新画布尺寸,使其刚好只覆盖图像区域 MyCanvasDraw.Width = ratio * _drawimg.Width; MyCanvasDraw.Height = ratio * _drawimg.Height; Canvas.SetLeft(MyCanvasDraw, translateX); Canvas.SetTop(MyCanvasDraw, translateY); MyCanvasDraw.ClipToBounds = true; MyCanvas.Width = ratio * _drawimg.Width; MyCanvas.Height = ratio * _drawimg.Height; Canvas.SetLeft(MyCanvas, translateX); Canvas.SetTop(MyCanvas, translateY); DrawImage.Source = _drawimg; OrigImage.Source = _origimg; if (_dstImgWin == null || CheckModelResult.IsChecked.Value == false) { OrigImage.Source = _origimg; } else { OrigImage.Source = _dstImgWin; } //if(_dstImgWin != null) //{ // DrawImage.Source = _dstImgWin; //} } /// /// 更新显示已有的轮廓 /// private void UpdateLesionsInCanvas() { if (_drawimg == null) { return; } RemoveContourInCanvas("drawing"); RemoveLineInCanvas(EnumCanvasLineType.Horizontal, "drawing"); RemoveLineInCanvas(EnumCanvasLineType.Vertical, "drawing"); // 显示新的病灶 if (_showDrawingResult) { for (int ni = 0; ni < _lesions.Count; ni++) { // 显示病灶轮廓, 注意,所有点需转到Canvas坐标系下 List contour = _lesions[ni].Contour; if (contour.Count > 0) { List contourInCanvas = new List(); for (int nj = 0; nj < contour.Count; nj++) { contourInCanvas.Add(GetPosInCanvas(contour[nj])); } if (ni == _lesionIndex) { DrawContourInCanvas(contourInCanvas, EnumCanvasItemType.Choosed, ni.ToString()); } else { DrawContourInCanvas(contourInCanvas, EnumCanvasItemType.Existed, ni.ToString()); } } // 显示病灶横轴,注意,所有点需转到Canvas坐标系下 Point2D hP1 = _lesions[ni].HorizontalPoint1; Point2D hP2 = _lesions[ni].HorizontalPoint2; if (hP1 != null && hP2 != null) { System.Windows.Point hP1InCanvas = GetPosInCanvas(hP1); System.Windows.Point hP2InCanvas = GetPosInCanvas(hP2); if (ni == _lesionIndex) { DrawLineInCanvas(hP1InCanvas, hP2InCanvas, EnumCanvasLineType.Horizontal, EnumCanvasItemType.Choosed, ni.ToString()); } else { DrawLineInCanvas(hP1InCanvas, hP2InCanvas, EnumCanvasLineType.Horizontal, EnumCanvasItemType.Existed, ni.ToString()); } } // 显示病灶纵轴,注意所有点需转到Canvas坐标系下 Point2D vP1 = _lesions[ni].VerticalPoint1; Point2D vP2 = _lesions[ni].VerticalPoint2; if (vP1 != null && vP2 != null) { System.Windows.Point vP1InCanvas = GetPosInCanvas(vP1); System.Windows.Point vP2InCanvas = GetPosInCanvas(vP2); if (ni == _lesionIndex) { DrawLineInCanvas(vP1InCanvas, vP2InCanvas, EnumCanvasLineType.Vertical, EnumCanvasItemType.Choosed, ni.ToString()); } else { DrawLineInCanvas(vP1InCanvas, vP2InCanvas, EnumCanvasLineType.Vertical, EnumCanvasItemType.Existed, ni.ToString()); } } } } } /// /// 更新显示已有的病灶分级 /// private void UpdateLesionsIndex() { ComboBoxLesionsLabel.SelectedIndex = -1; for (int ni = 0; ni < _lesionsLabels.Count; ni++) { if (ni == _lesionIndex) { ComboBoxLesionsLabel.SelectedIndex = _lesionsLabels[ni]; } else { //ComboBoxLesionsLabel.SelectedIndex = -1; } } //ComboBoxLesionsLabel.SelectedIndex = _lesionsLabels[_lesionIndex]; } /// /// 绘制轮廓 /// /// /// /// private void DrawContourInCanvas(List contour, EnumCanvasItemType type, string name) { if (_drawimg == null) { return; } RemoveContourInCanvas(name); Polyline contourLines = new Polyline { StrokeThickness = 1, Stroke = GetContourBrushColor(type), Points = new System.Windows.Media.PointCollection(contour) }; MyCanvasDraw.Children.Add(contourLines); MyCanvasDraw.RegisterName("Contour_" + name, contourLines); } /// /// 清除已绘制的轮廓 /// /// private void RemoveContourInCanvas(string name) { string contourName = "Contour_" + name; if (MyCanvasDraw.FindName(contourName) is Polyline contourExists) { MyCanvasDraw.Children.Remove(contourExists); MyCanvasDraw.UnregisterName(contourName); } } /// /// 画线 /// /// /// /// /// /// private void DrawLineInCanvas(System.Windows.Point startPos, System.Windows.Point endPos, EnumCanvasLineType lineType, EnumCanvasItemType type, string name) { if (_drawimg == null) { return; } RemoveLineInCanvas(lineType, name); System.Windows.Shapes.Line line = new System.Windows.Shapes.Line { X1 = startPos.X, Y1 = startPos.Y, X2 = endPos.X, Y2 = endPos.Y, StrokeThickness = 1, Stroke = GetLineBrushColor(type, lineType) }; MyCanvasDraw.Children.Add(line); string lineName; if (lineType == EnumCanvasLineType.Horizontal) { lineName = "Line_H_" + name; } else { lineName = "Line_V_" + name; } MyCanvasDraw.RegisterName(lineName, line); } /// /// 移除已画的线 /// /// /// private void RemoveLineInCanvas(EnumCanvasLineType lineType, string name) { string lineName; if (lineType == EnumCanvasLineType.Horizontal) { lineName = "Line_H_" + name; } else { lineName = "Line_V_" + name; } if (MyCanvasDraw.FindName(lineName) is System.Windows.Shapes.Line lineExists) { MyCanvasDraw.Children.Remove(lineExists); MyCanvasDraw.UnregisterName(lineName); } } /// /// 设置横轴纵轴线的颜色 /// /// /// /// private System.Windows.Media.Brush GetLineBrushColor(EnumCanvasItemType itemType, EnumCanvasLineType lineType) { switch (itemType) { case EnumCanvasItemType.Drawing: if (lineType == EnumCanvasLineType.Horizontal) { return System.Windows.Media.Brushes.DarkGreen; } else { return System.Windows.Media.Brushes.DarkBlue; } case EnumCanvasItemType.Existed: if (lineType == EnumCanvasLineType.Horizontal) { return System.Windows.Media.Brushes.LightGreen; } else { return System.Windows.Media.Brushes.LightBlue; } default: if (lineType == EnumCanvasLineType.Horizontal) { return System.Windows.Media.Brushes.Green; } else { return System.Windows.Media.Brushes.Blue; } } } /// /// 设置轮廓线的颜色 /// /// /// private System.Windows.Media.Brush GetContourBrushColor(EnumCanvasItemType itemType) { switch (itemType) { case EnumCanvasItemType.Drawing: return System.Windows.Media.Brushes.OrangeRed; case EnumCanvasItemType.Existed: return System.Windows.Media.Brushes.LightYellow; default: return System.Windows.Media.Brushes.Orange; } } /// /// 更新该图上的病灶 /// private void LesionsUpdated() { ComboBoxLesions.SelectionChanged -= OnLesionSelectionChanged; ComboBoxLesions.Items.Clear(); for (int ni = 0; ni < _lesions.Count; ni++) { ComboBoxLesions.Items.Add("病灶 " + ni.ToString()); } if (ComboBoxLesions.SelectedIndex != _lesionIndex) { ComboBoxLesions.SelectedIndex = _lesionIndex; } if (_lesionIndex < 0) { UserControlLesionSelected.SetLesionEmpty(); } else { UserControlLesionSelected.SetLesion(_lesions[_lesionIndex]); } ComboBoxLesions.SelectionChanged += OnLesionSelectionChanged; UpdateLesionsInCanvas(); UpdateLesionsIndex(); } /// /// 要加载的图像序号发生了改变 /// private void CurrentImgIndexUpdated() { if (_imgIndex < 0 || _imgIndex >= _allImages.Count /*- 1*/) { throw new ArgumentOutOfRangeException("待更新的图像序号超出范围."); } TextBlockCurrentIndex.Text = _imgIndex.ToString(); LesionDesGTImgInfo imgInfo = _allImages[_imgIndex]; string imgPath = System.IO.Path.Combine(_imageDataFolder, imgInfo.ImageId + ".jpg"); //string imgPath = imgInfo.ImageId; if (!File.Exists(imgPath)) { throw new FileNotFoundException("找不到文件:" + imgPath); } _image = new Bitmap(imgPath); _drawimg = RawImageShowUtils.BitmapToBitmapImage(_image); _origimg = RawImageShowUtils.BitmapToBitmapImage(_image); //image.Dispose(); ImageUpdated(); // 先清除所有已有显示 for (int ni = 0; ni < _lesions.Count; ni++) { RemoveContourInCanvas(ni.ToString()); RemoveLineInCanvas(EnumCanvasLineType.Horizontal, ni.ToString()); RemoveLineInCanvas(EnumCanvasLineType.Vertical, ni.ToString()); } int num = _drawingPoints.Count; if (num > 0) { // 更新显示正在绘制的轮廓线 RemoveContourInCanvasForDrawPts("drawingPt"); } // 再更新 _lesions = imgInfo.Lesions; _lesionsLabels = imgInfo.Label; _modified = false; if (_lesions.Count <= 0) { _lesionIndex = -1; ComboBoxLesionsLabel.SelectedIndex = -1; } else { _lesionIndex = 0; ComboBoxLesionsLabel.SelectedIndex = _lesionsLabels[_lesionIndex]; } LesionsUpdated(); } /// /// 收到LesionInfoSelector发来的事件 /// /// /// private void OnLesionInfoSelectorEventOccur(object sender, LesionInfoEventArgs e) { switch (e.EventType) { case EnumLesionInfoEventType.LesionInfoUpdated: _modified = true; if (_lesions.Count <= 0 && _lesionIndex < 0) { _lesions.Add(UserControlLesionSelected.Lesion); _lesionIndex = 0; _lesionsLabels.Add(-1); } else { _lesions[_lesionIndex] = UserControlLesionSelected.Lesion; //_lesionsLabels.Add(-1); } LesionsUpdated(); break; case EnumLesionInfoEventType.DrawContour: _mouseOper = EnumMouseOperType.DrawingContour; break; case EnumLesionInfoEventType.DrawHorizontal: _mouseOper = EnumMouseOperType.DrawingHorizonLines; break; case EnumLesionInfoEventType.DrawVertical: _mouseOper = EnumMouseOperType.DrawingVerticalLines; break; case EnumLesionInfoEventType.DrawPoint: _mouseOper = EnumMouseOperType.DrawingPoint; break; } } /// /// 将Canvas上的点转换到图像坐标系下 /// /// /// private Point2D GetPosInOrigImage(System.Windows.Point posInCanvas) { if (_drawimg != null) { int x = Convert.ToInt32(posInCanvas.X / MyCanvasDraw.Width * _drawimg.Width); int y = Convert.ToInt32(posInCanvas.Y / MyCanvasDraw.Height * _drawimg.Height); return new Point2D(x, y); } else { return new Point2D(0, 0); } } /// /// 将图像上的点转换到Canvas坐标系下 /// /// /// private System.Windows.Point GetPosInCanvas(Point2D posInOrigImg) { if (_drawimg != null) { int x = Convert.ToInt32(posInOrigImg.X / _drawimg.Width * MyCanvasDraw.Width); int y = Convert.ToInt32(posInOrigImg.Y / _drawimg.Height * MyCanvasDraw.Height); return new System.Windows.Point(x, y); } else { return new System.Windows.Point(0, 0); } } /// /// 计算两点之间的距离 /// /// /// /// private double PointDistance(System.Windows.Point point1, System.Windows.Point point2) { return Math.Sqrt(Math.Pow(point1.X - point2.X, 2) + Math.Pow(point1.Y - point2.Y, 2)); } #endregion #region 创建标准描述数据库相关的函数 /// /// 创建数据库 /// private bool CreateDataBase() { if (File.Exists(_dbPath)) { //throw new Exception("数据库已存在,请检查."); return false ; } // 创建数据库文件 SQLiteConnection dbCon = new SQLiteConnection("Data Source=" + _dbPath); dbCon.Open(); SQLiteCommand dbCmd; dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "create table if not exists LesionDesGTDatas(ImageId varchar(16),Lesions varchar(16),Label varchar(16))"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "create table if not exists LastModification(ImageId varchar(16))"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); dbCon.Close(); dbCon.Dispose(); return true; } /// /// 添加新的图像到数据集里 /// /// private void AddNewImages(string origImageFolder) { // 如果文件夹不存在,则创建 if (!Directory.Exists(_imageDataFolder)) { Directory.CreateDirectory(_imageDataFolder); } // 已有多少图片 SQLiteConnection dbCon = new SQLiteConnection("Data Source=" + _dbPath); dbCon.Open(); SQLiteCommand dbCmd; SQLiteDataReader dbReader; // 遍历该文件夹下所有图片 DirectoryInfo origImgDir = new DirectoryInfo(origImageFolder); FileInfo[] files = origImgDir.GetFiles(); foreach (var file in files) { Bitmap image = new Bitmap(file.FullName); RawImage rawImg = RawImageShowUtils.BitmapToRawImage(image); //string hashCode = ComputeHashCode(rawImg.DataBuffer); string temp; int idx = file.FullName.LastIndexOf("\\"); temp = file.FullName.Substring(idx); string[] strs1 = temp.Split('\\'); temp = strs1[1]; string[] strs2 = System.Text.RegularExpressions.Regex.Split(temp, ".jpg", System.Text.RegularExpressions.RegexOptions.IgnoreCase); string ImgId = strs2[0]; string hashCode = ImgId; image.Dispose(); rawImg.Dispose(); // 查找该图片是否已经存在 dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "select * from LesionDesGTDatas where ImageId='" + hashCode + "'"; dbReader = dbCmd.ExecuteReader(); if (dbReader.HasRows) { dbReader.Close(); dbCmd.Dispose(); continue; } // 以哈希值作为该图片的id,同时也作为图像名,复制原始图像到指定目录下 //string imgdstPath = System.IO.Path.Combine(_imageDataFolder, hashCode + ".jpg"); //File.Copy(file.FullName, imgdstPath); // 将该图相关信息存到数据库里 List lesions = new List(); string strLesions = JsonConvert.SerializeObject(lesions); List LesionsLabel = new List(); string strLesionsLabel = JsonConvert.SerializeObject(LesionsLabel); dbCmd = dbCon.CreateCommand(); dbCmd.CommandText = "insert into LesionDesGTDatas(ImageId,Lesions,Label) select '" + hashCode + "','" + strLesions + "','" + strLesionsLabel + "'"; dbCmd.ExecuteNonQuery(); dbCmd.Dispose(); } dbCon.Close(); dbCon.Dispose(); } #endregion private void OnBtnModelImageClicked(object sender, RoutedEventArgs e) { if(_image != null) { DetectImage(_image); } } /// /// 使用模型检测,并显示在标注结果界面上 /// /// private void DetectImage(Bitmap image) { string name = _allImages[_imgIndex].ImageId; RawImage rawImg = null; //rawImg = RawImageShowUtils.BitmapToRawImage(image); var rawImage = RawImageShowUtils.BitmapToRawImage(image); _caseId = Guid.NewGuid().ToString(); _dataId = name; _readingVideo = false; var extendData = new Dictionary(); extendData.Add("CaseId", _caseId); extendData.Add("DataId", _dataId); extendData.Add("IsVideo", _readingVideo); extendData.Add("TimeStamp", (double)_frameIndex); _processId = _module.StartProcess(); var input = new ImageInputData(rawImage, extendData); IDetectedObject[] result = _module.PushOnePieceOfData(_processId, input); _newModelResult = result; _module.EndProcess(_processId); //var diagResult = _diagSystem.EvaluateOneImage(rawImg); if(result != null) { var dstimage = ShowDiagResultsOnImage(image, result);// ModelResultShow(); _dstImgWin = RawImageShowUtils.BitmapToBitmapImage(dstimage); Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() => { if (_dstImgWin == null || CheckModelResult.IsChecked.Value == false) { OrigImage.Source = _origimg; } else { OrigImage.Source = _dstImgWin; } } )); dstimage.Dispose(); } else { System.Windows.MessageBox.Show("模型检测失败"); } } private Bitmap ShowDiagResultsOnImage(Bitmap image, IDetectedObject[] diagResult) { int breastLesionNum = 0; Bitmap dstimage = image.Clone(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb); //var organGt = diagResult.DiagResultsForEachOrgan; foreach (var resultsPerOrgan in diagResult) { var Ilabel = resultsPerOrgan.Label; var nameOrgan = Ilabel.GroupName; int indexLabel = Ilabel.Index; if (nameOrgan != "AI.Vaid.Breast.Lesion") { continue; } //if (resultsPerOrgan.Organ == EnumOrgans.Breast) { using (var g = Graphics.FromImage(dstimage)) { int num = 0; string strDescriptionShape = string.Empty; string strDescriptionOrientation = string.Empty; string strDescriptionEcho = string.Empty; string strDescriptionBound = string.Empty; string strDescriptionMargin = string.Empty; System.Drawing.Brush brush = System.Drawing.Brushes.Green; List CurImageLesion = new List(); if (_modelResult != null) { _modelResult = null; _modelResult = new LesionDesGTImgInfo(); _modelResult.Lesions = new List(); _modelResult.Label = new List(); } var resultConversion = AIModuleResultShowUtils.GetObjectStr(resultsPerOrgan); if (resultsPerOrgan.Contour?.Contours.Length > 0) { //ShowContour(moduleResult.Contour, brush, null, transform); int count = resultsPerOrgan.Contour.Contours.Length; LesionInfo lesion = new LesionInfo(); for (int i = 0; i < count; i++) { var contourPoints = resultsPerOrgan.Contour.Contours[i]; int pointCount = contourPoints.Points.Length; //var points = new List(); System.Drawing.PointF[] lesionContour = new PointF[pointCount]; List points = new List(); for (int j = 0; j < pointCount; j++) { var point = new System.Windows.Point(contourPoints.Points[j].X, contourPoints.Points[j].Y); lesionContour[j].X = contourPoints.Points[j].X; lesionContour[j].Y = contourPoints.Points[j].Y; Point2D pt = new Point2D(contourPoints.Points[j].X, contourPoints.Points[j].Y); points.Add(pt); lesion.Contour.Add(pt); } g.DrawPolygon(new System.Drawing.Pen(brush, 2), lesionContour); var desResult = resultsPerOrgan.Description; var type = desResult.GetType(); string strDescription = string.Empty; //if (type == typeof(BreastLesionDescription)) { foreach (var key in desResult.Descriptions.Keys) { if (key == "Shape") { EnumDesShapeValue sss = new EnumDesShapeValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "Oval": des = "椭圆形"; sss = EnumDesShapeValue.Oval; break; case "Round": des = "类圆形"; sss = EnumDesShapeValue.Round; break; case "Irregular": des = "不规则形"; sss = EnumDesShapeValue.Irregular; break; } lesion.Shape = sss; strDescription += "形状:" + des + Environment.NewLine; } if (key == "Orientation") { EnumDesOrientationValue sss = new EnumDesOrientationValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "Parallel": des = "平行"; sss = EnumDesOrientationValue.Parallel; break; case "NonParallel": des = "非平行"; sss = EnumDesOrientationValue.NonParallel; break; } lesion.Orientation = sss; strDescription += "生长方向:" + des + Environment.NewLine; } if (key == "EchoPattern") { EnumDesEchoPatternValue sss = new EnumDesEchoPatternValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "Anechoic": des = "无回声"; sss = EnumDesEchoPatternValue.Anechoic; break; case "Hypoechoic": des = "低回声"; sss = EnumDesEchoPatternValue.Hypoechoic; break; case "Isoechoic": des = "等回声"; sss = EnumDesEchoPatternValue.Isoechoic; break; case "Hyperechoic": des = "高回声"; sss = EnumDesEchoPatternValue.Hyperechoic; break; case "Complex": des = "混合回声"; sss = EnumDesEchoPatternValue.Complex; break; } lesion.EchoPattern = sss; strDescription += "回声类型:" + des + Environment.NewLine; } if (key == "Boundary") { EnumDesLesionBoundaryValue sss = new EnumDesLesionBoundaryValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "AbruptInterface": des = "清晰"; sss = EnumDesLesionBoundaryValue.AbruptInterface; break; case "EchogenicHalo": des = "模糊"; sss = EnumDesLesionBoundaryValue.EchogenicHalo; break; } lesion.Boundary = sss; strDescription += "边界:" + des + Environment.NewLine; } if (key == "Margin") { EnumDesMarginValue sss = new EnumDesMarginValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "Circumscribed": des = "光整"; sss = EnumDesMarginValue.Circumscribed; break; case "NonCircumscribed": des = "不光整"; sss = EnumDesMarginValue.NonCircumscribed; break; } lesion.Margin = sss; strDescription += "边缘:" + des + Environment.NewLine; } } } var rect = resultsPerOrgan.BoundingBox.Contour.BoundingBox(); var roiBox = resultsPerOrgan.BoundingBox; var ss = roiBox.Contour.Points; var lesionSize = Array.Find(resultsPerOrgan.Measurements, x => x.GetType() == typeof(TransverseLongitudinalDiameterMeasurement)); var size = (TransverseLongitudinalDiameterMeasurement)lesionSize; var pointLineH1 = new System.Windows.Point(size.TransverseDiameterMarkPosition.LineStart.X, size.TransverseDiameterMarkPosition.LineStart.Y); var pointLineH2 = new System.Windows.Point(size.TransverseDiameterMarkPosition.LineEnd.X, size.TransverseDiameterMarkPosition.LineEnd.Y); var pointLineV1 = new System.Windows.Point(size.LongitudinalDiameterMarkPosition.LineStart.X, size.LongitudinalDiameterMarkPosition.LineStart.Y); var pointLineV2 = new System.Windows.Point(size.LongitudinalDiameterMarkPosition.LineEnd.X, size.LongitudinalDiameterMarkPosition.LineEnd.Y); System.Drawing.Point[] axisH = new System.Drawing.Point[2]; System.Drawing.Point[] axisV = new System.Drawing.Point[2]; axisH[0].X = (int)pointLineH1.X; axisH[0].Y = (int)pointLineH1.Y; axisH[1].X = (int)pointLineH2.X; axisH[1].Y = (int)pointLineH2.Y; axisV[0].X = (int)pointLineV1.X; axisV[0].Y = (int)pointLineV1.Y; axisV[1].X = (int)pointLineV2.X; axisV[1].Y = (int)pointLineV2.Y; System.Drawing.Pen pen_h = new System.Drawing.Pen(System.Drawing.Brushes.PaleGreen, 2); g.DrawLines(pen_h, axisH); //横轴,浅绿色 System.Drawing.Pen pen_v = new System.Drawing.Pen(System.Drawing.Brushes.Red, 1); g.DrawLines(pen_v, axisV); //纵轴,红色 var Measurements = resultsPerOrgan.Measurements; var len = Measurements.Length; if(len > 0) { var marks = Measurements[0].MeasureMarks; int lenM = marks.Length; var con = marks[0].Contour.Points; int numC = con.Length; } } _modelResult.Lesions.Add(lesion); _modelResult.Label.Add(indexLabel); num++; } g.Dispose(); } } } if (breastLesionNum == 0) { //MessageBox.Show("未检测出病灶"); } else { _lesionOriModelIndex = 0; ModelComboBoxOriUpdated(); } return dstimage; } /// /// 复制模型结果 /// /// /// private void OnBtnCopyModelResultClicked(object sender, RoutedEventArgs e) { // 保存当前图的结果 //_modified = true; //if (_modified) { if(_allImages[_imgIndex].Lesions.Count > 0) { System.Windows.MessageBox.Show("已存在病灶信息,请先删除右图标注数据"); return; } if(_modelResult.Lesions.Count > 0) { if (_modelResult.Lesions[0].Contour.Count >0) { _lesions = _modelResult.Lesions; _lesionsLabels = _modelResult.Label;// _lesionsModelLabels; _allImages[_imgIndex].Lesions = _lesions; _allImages[_imgIndex].Label = _lesionsLabels; CopyModelToCurrentImgUpdated(); _lesionIndex = ComboBoxLesions.SelectedIndex; //_lesionsLabels = _lesionsModelLabels; //分级 ComboBoxLesionsLabel.SelectedIndex = _lesionsLabels[_lesionIndex] ; _modified = true; } } else { if (_image != null) { DetectImage(_image); } if (_modelResult.Lesions[0].Contour.Count > 0) { _lesions = _modelResult.Lesions; _lesionsLabels = _modelResult.Label;// _lesionsModelLabels; _allImages[_imgIndex].Lesions = _lesions; _allImages[_imgIndex].Label = _lesionsLabels; CopyModelToCurrentImgUpdated(); _lesionIndex = ComboBoxLesions.SelectedIndex; //_lesionsLabels = _lesionsModelLabels; //分级 ComboBoxLesionsLabel.SelectedIndex = _lesionsLabels[_lesionIndex]; _modified = true; } return; } } } /// /// 复制模型结果显示到右边界面 /// private void CopyModelToCurrentImgUpdated() { if (_imgIndex < 0 || _imgIndex >= _allImages.Count/* - 1*/) { throw new ArgumentOutOfRangeException("待更新的图像序号超出范围."); } TextBlockCurrentIndex.Text = _imgIndex.ToString(); LesionDesGTImgInfo imgInfo = _allImages[_imgIndex]; string imgPath = System.IO.Path.Combine(_imageDataFolder, imgInfo.ImageId + ".jpg"); //string imgPath = imgInfo.ImageId; if (!File.Exists(imgPath)) { throw new FileNotFoundException("找不到文件:" + imgPath); } _image = new Bitmap(imgPath); _drawimg = RawImageShowUtils.BitmapToBitmapImage(_image); _origimg = RawImageShowUtils.BitmapToBitmapImage(_image); //image.Dispose(); ImageUpdated(); // 先清除所有已有显示 for (int ni = 0; ni < _lesions.Count; ni++) { RemoveContourInCanvas(ni.ToString()); RemoveLineInCanvas(EnumCanvasLineType.Horizontal, ni.ToString()); RemoveLineInCanvas(EnumCanvasLineType.Vertical, ni.ToString()); } // 再更新 if (_lesions.Count <= 0) { _lesionIndex = -1; } else { _lesionIndex = 0; } ModelLesionsUpdated(); } /// /// 将模型结果更新到图上的病灶 /// private void ModelLesionsUpdated() { ComboBoxLesions.SelectionChanged -= OnLesionSelectionChanged; ComboBoxLesions.Items.Clear(); for (int ni = 0; ni < _modelResult.Lesions.Count; ni++) { ComboBoxLesions.Items.Add("病灶 " + ni.ToString()); } if (ComboBoxLesions.SelectedIndex != _lesionIndex) { ComboBoxLesions.SelectedIndex = _lesionIndex; } _lesionIndex = 0;//强制为0 if (_lesionIndex < 0) { UserControlLesionSelected.SetLesionEmpty(); } else { //病灶数据此时由模型给出,将病灶信息赋给LesionInfoSelector::UserControlLesionSelected UserControlLesionSelected.SetLesion(_modelResult.Lesions[_lesionIndex]); } ComboBoxLesions.SelectionChanged += OnLesionSelectionChanged; UpdateModelLesionsInCanvas(); //_lesionIndex = -1; } /// /// 更新显示已有的轮廓 /// private void UpdateModelLesionsInCanvas() { if (_drawimg == null) { return; } RemoveContourInCanvas("drawing"); RemoveLineInCanvas(EnumCanvasLineType.Horizontal, "drawing"); RemoveLineInCanvas(EnumCanvasLineType.Vertical, "drawing"); // 显示新的病灶 if(_showDrawingResult) { for (int ni = 0; ni < _modelResult.Lesions.Count; ni++) { // 显示病灶轮廓, 注意,所有点需转到Canvas坐标系下 List contour = _modelResult.Lesions[ni].Contour; if (contour.Count > 0) { List contourInCanvas = new List(); for (int nj = 0; nj < contour.Count; nj++) { contourInCanvas.Add(GetPosInCanvas(contour[nj])); } if (ni == _lesionIndex) { DrawContourInCanvas(contourInCanvas, EnumCanvasItemType.Choosed, ni.ToString()); } else { DrawContourInCanvas(contourInCanvas, EnumCanvasItemType.Existed, ni.ToString()); } } // 显示病灶横轴,注意,所有点需转到Canvas坐标系下 Point2D hP1 = _modelResult.Lesions[ni].HorizontalPoint1; Point2D hP2 = _modelResult.Lesions[ni].HorizontalPoint2; if (hP1 != null && hP2 != null) { System.Windows.Point hP1InCanvas = GetPosInCanvas(hP1); System.Windows.Point hP2InCanvas = GetPosInCanvas(hP2); if (ni == _lesionIndex) { DrawLineInCanvas(hP1InCanvas, hP2InCanvas, EnumCanvasLineType.Horizontal, EnumCanvasItemType.Choosed, ni.ToString()); } else { DrawLineInCanvas(hP1InCanvas, hP2InCanvas, EnumCanvasLineType.Horizontal, EnumCanvasItemType.Existed, ni.ToString()); } } // 显示病灶纵轴,注意所有点需转到Canvas坐标系下 Point2D vP1 = _modelResult.Lesions[ni].VerticalPoint1; Point2D vP2 = _modelResult.Lesions[ni].VerticalPoint2; if (vP1 != null && vP2 != null) { System.Windows.Point vP1InCanvas = GetPosInCanvas(vP1); System.Windows.Point vP2InCanvas = GetPosInCanvas(vP2); if (ni == _lesionIndex) { DrawLineInCanvas(vP1InCanvas, vP2InCanvas, EnumCanvasLineType.Vertical, EnumCanvasItemType.Choosed, ni.ToString()); } else { DrawLineInCanvas(vP1InCanvas, vP2InCanvas, EnumCanvasLineType.Vertical, EnumCanvasItemType.Existed, ni.ToString()); } } } } } /// /// 将模型检测出的结果,显示在AI结果界面上 /// //private void ShowModelResult() //{ // if (_image != null) // { // DetectImage(_image); // if (_modelResult.Lesions.Count > 0) // { // _lesions = _modelResult.Lesions; // _lesionsLabels = _modelResult.Label;// _lesionsModelLabels; // if (_lesions.Count <= 0) // { // _lesionIndex = -1; // } // else // { // _lesionIndex = 0; // } // ComboBoxLesions.SelectedIndex = _lesionIndex; // ModelLesionsUpdated(); // //_lesionIndex = ComboBoxLesions.SelectedIndex; // } // } //} private void OnCheckedCheckModelResult(object sender, RoutedEventArgs e) { _showModelResult = true; OrigImage.Source = _dstImgWin; } private void OnUncheckedCheckModelResult(object sender, RoutedEventArgs e) { _showModelResult = false; OrigImage.Source = _origimg; } private void OnModelLesionSelectionChanged(object sender, SelectionChangedEventArgs e) { _lesionOriModelIndex = ComboBoxOriLesions.SelectedIndex; ModelResultShow(); ModelComboBoxOriUpdated(); } /// /// 显示对应的模型检测结果 /// private void ModelComboBoxOriUpdated() { ComboBoxOriLesions.SelectionChanged -= OnModelLesionSelectionChanged; ComboBoxOriLesions.Items.Clear(); for (int ni = 0; ni < _modelResult.Lesions.Count; ni++) { ComboBoxOriLesions.Items.Add("病灶 " + ni.ToString()); } if (ComboBoxOriLesions.SelectedIndex != _lesionOriModelIndex) { ComboBoxOriLesions.SelectedIndex = _lesionOriModelIndex; } ComboBoxOriLesions.SelectionChanged += OnModelLesionSelectionChanged; //UpdateModelLesionsInCanvas(); } private void ModelResultShow() { if (_modelResult.Lesions != null) { if (_modelResult.Lesions.Count > 0) { var lesionCur = _modelResult.Lesions[_lesionOriModelIndex]; int lesionLabel = _modelResult.Label[_lesionOriModelIndex]; string strLabel = string.Empty; switch (lesionLabel) { case 0: strLabel = "0"; break; case 1: strLabel = "脂肪瘤"; break; case 2: strLabel = "2级"; break; case 3: strLabel = "3级"; break; case 4: strLabel = "4a级"; break; case 5: strLabel = "4b级"; break; case 6: strLabel = "4c级"; break; case 7: strLabel = "5级"; break; } string strShape = string.Empty; switch (lesionCur.Shape) { case EnumDesShapeValue.Oval: strShape = "椭圆形"; break; case EnumDesShapeValue.Round: strShape = "圆形"; break; case EnumDesShapeValue.Irregular: strShape = "不规则"; break; } string strOrientation = string.Empty; switch (lesionCur.Orientation) { case EnumDesOrientationValue.Parallel: strOrientation = "平行"; break; case EnumDesOrientationValue.NonParallel: strOrientation = "非平行"; break; } string strMargin = string.Empty; switch (lesionCur.Margin) { case EnumDesMarginValue.Circumscribed: strMargin = "光整"; break; case EnumDesMarginValue.NonCircumscribed: strMargin = "不光整"; break; } string strEcho = string.Empty; switch (lesionCur.EchoPattern) { case EnumDesEchoPatternValue.Anechoic: strEcho = "无回声"; break; case EnumDesEchoPatternValue.Hypoechoic: strEcho = "低回声"; break; case EnumDesEchoPatternValue.Hyperechoic: strEcho = "高回声"; break; case EnumDesEchoPatternValue.Strongechoic: strEcho = "强回声"; break; case EnumDesEchoPatternValue.Complex: strEcho = "混合回声"; break; case EnumDesEchoPatternValue.Isoechoic: strEcho = "等回声"; break; } string strBound = string.Empty; switch (lesionCur.Boundary) { case EnumDesLesionBoundaryValue.AbruptInterface: strBound = "清晰"; break; case EnumDesLesionBoundaryValue.EchogenicHalo: strBound = "模糊"; break; } Point2D horPt1 = lesionCur.HorizontalPoint1; Point2D horPt2 = lesionCur.HorizontalPoint2; Point2D verPt1 = lesionCur.VerticalPoint1; Point2D verPt2 = lesionCur.VerticalPoint2; strLabel = "0"; //add TextBlockLabel.Text = "等级:" + strLabel; TextBlockShape.Text = "形状:" + strShape; TextBlockOrientation.Text = "生长方向:" + strOrientation; TextBlockEcho.Text = "回声类型:" + strEcho; TextBlockBound.Text = "边界:" + strBound; TextBlockMargin.Text = "边缘:" + strMargin; TextBlockHorizontal.Text = "横径:" + "{" + horPt1.X + "," + horPt1.Y + "}" + "{" + horPt2.X + "," + horPt2.Y + "}"; TextBlockVertical.Text = "纵径:" + "{" + verPt1.X + "," + verPt1.Y + "}" + "{" + verPt2.X + "," + verPt2.Y + "}"; }; } } private void OnLesionSelectionLabelChanged(object sender, SelectionChangedEventArgs e) { _lesionLabelIndex = ComboBoxLesionsLabel.SelectedIndex; if(_lesionsLabels.Count >0) { if (_lesionsLabels[_lesionIndex] < 0) { _lesionsLabels[_lesionIndex] = _lesionLabelIndex; } else { if(_lesionLabelIndex >0) { _lesionsLabels[_lesionIndex] = _lesionLabelIndex; } } //_lesionsLabels[_lesionIndex] = _lesionLabelIndex; } else { ComboBoxLesionsLabel.SelectedIndex = -1; _lesionLabelIndex = 0; } } private void InitializeComboBoxLesionsLabel() { // 分级 ComboBoxLesionsLabel.Items.Add("0"); ComboBoxLesionsLabel.Items.Add("脂肪瘤"); ComboBoxLesionsLabel.Items.Add("2级"); ComboBoxLesionsLabel.Items.Add("3级"); ComboBoxLesionsLabel.Items.Add("4a级"); ComboBoxLesionsLabel.Items.Add("4b级"); ComboBoxLesionsLabel.Items.Add("4c级"); ComboBoxLesionsLabel.Items.Add("5级"); } private void OnCheckedCheckDrawingResult(object sender, RoutedEventArgs e) { _showDrawingResult = true; //_image = new Bitmap(imgPath); //_drawingPoints; UpdateLesionsInCanvas(); ShowDrawingPts(); } private void ShowDrawingPts() { int num = _drawingPoints.Count; if (num > 0) { // 更新显示正在绘制的轮廓线 DrawContourInCanvas(_drawingPoints, EnumCanvasItemType.Drawing, "drawingPt"); } } private void OnUncheckedCheckDrawingResult(object sender, RoutedEventArgs e) { _showDrawingResult = false;; RemoveContourLine(); } private void RemoveContourLine() { if (_drawimg == null) { return; } // 先清空画布上旧的显示内容 for (int ni = 0; ni < _lesions.Count; ni++) { RemoveContourInCanvas(ni.ToString()); RemoveLineInCanvas(EnumCanvasLineType.Horizontal, ni.ToString()); RemoveLineInCanvas(EnumCanvasLineType.Vertical, ni.ToString()); } int num = _drawingPoints.Count; if (num > 0) { // 更新显示正在绘制的轮廓线 RemoveContourInCanvasForDrawPts("drawingPt"); } } private void RemoveContourInCanvasForDrawPts(string name) { string contourName = "Contour_" + name; if (MyCanvasDraw.FindName(contourName) is Polyline contourExists) { MyCanvasDraw.Children.Remove(contourExists); MyCanvasDraw.UnregisterName(contourName); } } private void OnBtnSaveResultClicked(object sender, RoutedEventArgs e) { Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog(); openFileDialog.Filter = "图片文件|*.png;*.bmp;*.jpg;*.jpeg"; openFileDialog.Multiselect = true; openFileDialog.Title = "选择一幅或多幅图像"; if (openFileDialog.ShowDialog() ?? false) { foreach (string filename in openFileDialog.FileNames) { Bitmap img = new Bitmap(filename); string imgName = System.IO.Path.GetFileNameWithoutExtension(filename); string temp; int idx = filename.LastIndexOf("\\"); temp = filename.Substring(idx); string[] strs1 = temp.Split('\\'); temp = strs1[1]; //string[] strs2 = temp.Split(new char[4] { '.', 'j', 'p', 'g' }, 2); string[] strs2 = System.Text.RegularExpressions.Regex.Split(temp, ".jpg", System.Text.RegularExpressions.RegexOptions.IgnoreCase); string ImgId = strs2[0]; int imgIdx = _allImages.FindIndex(x => x.ImageId == ImgId); int imageId = imgIdx; //_showImg = img; if (imageId >= 0) { SaveModel(img, imageId, ImgId); Save(img, imageId, ImgId); JudgeResult(imageId); } } } } private void JudgeResult(int imageId) { if (_modelResult.Lesions.Count > 0 && _allImages[imageId].Lesions.Count > 0) { if (_modelResult.Lesions.Count != _allImages[imageId].Lesions.Count) { return; } else if(_modelResult.Lesions.Count==1 && _allImages[imageId].Lesions.Count ==1) { var shapeGt = _allImages[imageId].Lesions[0].Shape; var shapeModel = _modelResult.Lesions[0].Shape; if (shapeGt == EnumDesShapeValue.Oval && shapeModel == EnumDesShapeValue.Oval) { _Oval_Oval_num++; } else if (shapeGt == EnumDesShapeValue.Oval && shapeModel == EnumDesShapeValue.Round) { _Oval_Round_num++; } else if (shapeGt == EnumDesShapeValue.Oval && shapeModel == EnumDesShapeValue.Irregular) { _Oval_Irregular_num++; } if (shapeGt == EnumDesShapeValue.Round && shapeModel == EnumDesShapeValue.Oval) { _Round_Oval_num++; } else if (shapeGt == EnumDesShapeValue.Round && shapeModel == EnumDesShapeValue.Round) { _Round_Round_num++; } else if (shapeGt == EnumDesShapeValue.Round && shapeModel == EnumDesShapeValue.Irregular) { _Round_Irregular_num++; } if (shapeGt == EnumDesShapeValue.Irregular && shapeModel == EnumDesShapeValue.Oval) { _Irregular_Oval_num++; } else if (shapeGt == EnumDesShapeValue.Irregular && shapeModel == EnumDesShapeValue.Round) { _Irregular_Round_num++; } else if (shapeGt == EnumDesShapeValue.Irregular && shapeModel == EnumDesShapeValue.Irregular) { _Irregular_Irregular_num++; } var orientationGt = _allImages[imageId].Lesions[0].Orientation; var orientationModel = _modelResult.Lesions[0].Orientation; if (orientationGt == EnumDesOrientationValue.Parallel && orientationModel == EnumDesOrientationValue.Parallel) { _Parallel_Parallel_num++; } else if(orientationGt == EnumDesOrientationValue.Parallel && orientationModel == EnumDesOrientationValue.NonParallel) { _Parallel_NonParallel_num++; } if (orientationGt == EnumDesOrientationValue.NonParallel && orientationModel == EnumDesOrientationValue.Parallel) { _NonParallel_Parallel_num++; } else if (orientationGt == EnumDesOrientationValue.NonParallel && orientationModel == EnumDesOrientationValue.NonParallel) { _NonParallel_NonParallel_num++; } var echoGt = _allImages[imageId].Lesions[0].EchoPattern; var echoModel = _modelResult.Lesions[0].EchoPattern; if (echoGt == EnumDesEchoPatternValue.Anechoic && echoModel == EnumDesEchoPatternValue.Anechoic) { _Anechoic_Anechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Anechoic && echoModel == EnumDesEchoPatternValue.Hypoechoic) { _Anechoic_Hypoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Anechoic && echoModel == EnumDesEchoPatternValue.Isoechoic) { _Anechoic_Isoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Anechoic && echoModel == EnumDesEchoPatternValue.Hyperechoic) { _Anechoic_Hyperechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Anechoic && echoModel == EnumDesEchoPatternValue.Complex) { _Anechoic_Complex_num++; } if (echoGt == EnumDesEchoPatternValue.Hypoechoic && echoModel == EnumDesEchoPatternValue.Anechoic) { _Hypoechoic_Anechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Hypoechoic && echoModel == EnumDesEchoPatternValue.Hypoechoic) { _Hypoechoic_Hypoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Hypoechoic && echoModel == EnumDesEchoPatternValue.Isoechoic) { _Hypoechoic_Isoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Hypoechoic && echoModel == EnumDesEchoPatternValue.Hyperechoic) { _Hypoechoic_Hyperechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Hypoechoic && echoModel == EnumDesEchoPatternValue.Complex) { _Hypoechoic_Complex_num++; } if (echoGt == EnumDesEchoPatternValue.Isoechoic && echoModel == EnumDesEchoPatternValue.Anechoic) { _Isoechoic_Anechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Isoechoic && echoModel == EnumDesEchoPatternValue.Hypoechoic) { _Isoechoic_Hypoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Isoechoic && echoModel == EnumDesEchoPatternValue.Isoechoic) { _Isoechoic_Isoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Isoechoic && echoModel == EnumDesEchoPatternValue.Hyperechoic) { _Isoechoic_Hyperechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Isoechoic && echoModel == EnumDesEchoPatternValue.Complex) { _Isoechoic_Complex_num++; } if (echoGt == EnumDesEchoPatternValue.Hyperechoic && echoModel == EnumDesEchoPatternValue.Anechoic) { _Hyperechoic_Anechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Hyperechoic && echoModel == EnumDesEchoPatternValue.Hypoechoic) { _Hyperechoic_Hypoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Hyperechoic && echoModel == EnumDesEchoPatternValue.Isoechoic) { _Hyperechoic_Isoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Hyperechoic && echoModel == EnumDesEchoPatternValue.Hyperechoic) { _Hyperechoic_Hyperechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Hyperechoic && echoModel == EnumDesEchoPatternValue.Complex) { _Hyperechoic_Complex_num++; } if (echoGt == EnumDesEchoPatternValue.Complex && echoModel == EnumDesEchoPatternValue.Anechoic) { _Complex_Anechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Complex && echoModel == EnumDesEchoPatternValue.Hypoechoic) { _Complex_Hypoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Complex && echoModel == EnumDesEchoPatternValue.Isoechoic) { _Complex_Isoechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Complex && echoModel == EnumDesEchoPatternValue.Hyperechoic) { _Complex_Hyperechoic_num++; } else if (echoGt == EnumDesEchoPatternValue.Complex && echoModel == EnumDesEchoPatternValue.Complex) { _Complex_Complex_num++; } var boundGt = _allImages[imageId].Lesions[0].Boundary; var boundModel = _modelResult.Lesions[0].Boundary; if (boundGt == EnumDesLesionBoundaryValue.AbruptInterface && boundModel == EnumDesLesionBoundaryValue.AbruptInterface) { _AbruptInterface_AbruptInterface_num++; } else if (boundGt == EnumDesLesionBoundaryValue.AbruptInterface && boundModel == EnumDesLesionBoundaryValue.EchogenicHalo) { _AbruptInterface_EchogenicHalo_num++; } if (boundGt == EnumDesLesionBoundaryValue.EchogenicHalo && boundModel == EnumDesLesionBoundaryValue.AbruptInterface) { _EchogenicHalo_AbruptInterface_num++; } else if (boundGt == EnumDesLesionBoundaryValue.EchogenicHalo && boundModel == EnumDesLesionBoundaryValue.EchogenicHalo) { _EchogenicHalo_EchogenicHalo_num++; } var marginGt = _allImages[imageId].Lesions[0].Margin; var marginModel = _modelResult.Lesions[0].Margin; if (marginGt == EnumDesMarginValue.Circumscribed && marginModel == EnumDesMarginValue.Circumscribed) { _Circumscribed_NonCircumscribed_num++; } else if (marginGt == EnumDesMarginValue.Circumscribed && marginModel == EnumDesMarginValue.NonCircumscribed) { _Circumscribed_NonCircumscribed_num++; } if (marginGt == EnumDesMarginValue.NonCircumscribed && marginModel == EnumDesMarginValue.Circumscribed) { _NonCircumscribed_Circumscribed_num++; } else if (marginGt == EnumDesMarginValue.NonCircumscribed && marginModel == EnumDesMarginValue.NonCircumscribed) { _NonCircumscribed_NonCircumscribed_num++; } } } } public void SaveModel(Bitmap image, int imageId, string imageName) { string currentPath = System.Environment.CurrentDirectory; string newPath = System.IO.Path.Combine(currentPath, "result"); RawImage rawImg = null; rawImg = RawImageShowUtils.BitmapToRawImage(image); if(_newModelResult == null) { string name = _allImages[_imgIndex].ImageId; _caseId = Guid.NewGuid().ToString(); _dataId = name; _readingVideo = false; var extendData = new Dictionary(); extendData.Add("CaseId", _caseId); extendData.Add("DataId", _dataId); extendData.Add("IsVideo", _readingVideo); extendData.Add("TimeStamp", (double)_frameIndex); _processId = _module.StartProcess(); var input = new ImageInputData(rawImg, extendData); IDetectedObject[] result = _module.PushOnePieceOfData(_processId, input); _newModelResult = result; _module.EndProcess(_processId); } else { } //var diagResult = _diagSystem.EvaluateOneImage(rawImg); int breastLesionNum = 0; Bitmap dstimage = image.Clone(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.PixelFormat.Format24bppRgb); if (_newModelResult != null) { foreach (var moduleResult in _newModelResult) { var label = moduleResult.Label; var nameOrgan = label.GroupName; var Ilabel = moduleResult.Label; int indexLabel = Ilabel.Index; if (nameOrgan == "AI.Vaid.Breast.Lesion") { using (var g = Graphics.FromImage(dstimage)) { int num = 0; string strDescriptionShape = string.Empty; string strDescriptionOrientation = string.Empty; string strDescriptionEcho = string.Empty; string strDescriptionBound = string.Empty; string strDescriptionMargin = string.Empty; System.Drawing.Brush brush = System.Drawing.Brushes.Green; List CurImageLesion = new List(); if (moduleResult.Contour?.Contours.Length > 0) { int count = moduleResult.Contour.Contours.Length; for (int i = 0; i < count; i++) { brush = System.Drawing.Brushes.Green; int labelName = indexLabel; LesionInfo lesion = new LesionInfo(); var contourPoints = moduleResult.Contour.Contours[i]; int pointCount = contourPoints.Points.Length; var points = new List(); System.Drawing.PointF[] lesionContour = new PointF[pointCount]; for (int j = 0; j < pointCount; j++) { var point = new System.Windows.Point(contourPoints.Points[j].X, contourPoints.Points[j].Y); lesionContour[j].X = contourPoints.Points[j].X; lesionContour[j].Y = contourPoints.Points[j].Y; Point2D pt = new Point2D(contourPoints.Points[j].X, contourPoints.Points[j].Y); points.Add(pt); lesion.Contour.Add(pt); } g.DrawPolygon(new System.Drawing.Pen(brush, 2), lesionContour); var desResult = moduleResult.Description; var type = desResult.GetType(); string strDescription = string.Empty; { foreach (var key in desResult.Descriptions.Keys) { if (key == "Shape") { EnumDesShapeValue sss = new EnumDesShapeValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "Oval": des = "椭圆形"; sss = EnumDesShapeValue.Oval; break; case "Round": des = "类圆形"; sss = EnumDesShapeValue.Round; break; case "Irregular": des = "不规则形"; sss = EnumDesShapeValue.Irregular; break; } lesion.Shape = sss; strDescription += "形状:" + des + Environment.NewLine; } if (key == "Orientation") { EnumDesOrientationValue sss = new EnumDesOrientationValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "Parallel": des = "平行"; sss = EnumDesOrientationValue.Parallel; break; case "NonParallel": des = "非平行"; sss = EnumDesOrientationValue.NonParallel; break; } lesion.Orientation = sss; strDescription += "生长方向:" + des + Environment.NewLine; } if (key == "EchoPattern") { EnumDesEchoPatternValue sss = new EnumDesEchoPatternValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "Anechoic": des = "无回声"; sss = EnumDesEchoPatternValue.Anechoic; break; case "Hypoechoic": des = "低回声"; sss = EnumDesEchoPatternValue.Hypoechoic; break; case "Isoechoic": des = "等回声"; sss = EnumDesEchoPatternValue.Isoechoic; break; case "Hyperechoic": des = "高回声"; sss = EnumDesEchoPatternValue.Hyperechoic; break; case "Complex": des = "混合回声"; sss = EnumDesEchoPatternValue.Complex; break; } lesion.EchoPattern = sss; strDescription += "回声类型:" + des + Environment.NewLine; } if (key == "Boundary") { EnumDesLesionBoundaryValue sss = new EnumDesLesionBoundaryValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "AbruptInterface": des = "清晰"; sss = EnumDesLesionBoundaryValue.AbruptInterface; break; case "EchogenicHalo": des = "模糊"; sss = EnumDesLesionBoundaryValue.EchogenicHalo; break; } lesion.Boundary = sss; strDescription += "边界:" + des + Environment.NewLine; } if (key == "Margin") { EnumDesMarginValue sss = new EnumDesMarginValue(); string des = string.Empty; switch (desResult.Descriptions[key]) { case "Circumscribed": des = "光整"; sss = EnumDesMarginValue.Circumscribed; break; case "NonCircumscribed": des = "不光整"; sss = EnumDesMarginValue.NonCircumscribed; break; } lesion.Margin = sss; strDescription += "边缘:" + des + Environment.NewLine; } } } var rect = moduleResult.BoundingBox.Contour.BoundingBox(); var roiBox = moduleResult.BoundingBox; var ss = roiBox.Contour.Points; var lesionSize = Array.Find(moduleResult.Measurements, x => x.GetType() == typeof(TransverseLongitudinalDiameterMeasurement)); var size = (TransverseLongitudinalDiameterMeasurement)lesionSize; var pointLineH1 = new System.Windows.Point(size.TransverseDiameterMarkPosition.LineStart.X, size.TransverseDiameterMarkPosition.LineStart.Y); var pointLineH2 = new System.Windows.Point(size.TransverseDiameterMarkPosition.LineEnd.X, size.TransverseDiameterMarkPosition.LineEnd.Y); var pointLineV1 = new System.Windows.Point(size.LongitudinalDiameterMarkPosition.LineStart.X, size.LongitudinalDiameterMarkPosition.LineStart.Y); var pointLineV2 = new System.Windows.Point(size.LongitudinalDiameterMarkPosition.LineEnd.X, size.LongitudinalDiameterMarkPosition.LineEnd.Y); System.Drawing.Point[] axisH = new System.Drawing.Point[2]; System.Drawing.Point[] axisV = new System.Drawing.Point[2]; axisH[0].X = (int)pointLineH1.X; axisH[0].Y = (int)pointLineH1.Y; axisH[1].X = (int)pointLineH2.X; axisH[1].Y = (int)pointLineH2.Y; axisV[0].X = (int)pointLineV1.X; axisV[0].Y = (int)pointLineV1.Y; axisV[1].X = (int)pointLineV2.X; axisV[1].Y = (int)pointLineV2.Y; System.Drawing.Pen pen_h = new System.Drawing.Pen(System.Drawing.Brushes.PaleGreen, 2); g.DrawLines(pen_h, axisH); //横轴,浅绿色 System.Drawing.Pen pen_v = new System.Drawing.Pen(System.Drawing.Brushes.Red, 1); g.DrawLines(pen_v, axisV); //纵轴,红色 Font drawFont = new Font("黑体", 24); SolidBrush drawBrush = new SolidBrush(System.Drawing.Color.GreenYellow); float ptx = 10.0f; float pty = 0.0f + 20; string drawText = strDescriptionEcho;// g.DrawString(drawText, drawFont, drawBrush, ptx, pty + 30 * 4 * num); drawText = strDescriptionShape; g.DrawString(drawText, drawFont, drawBrush, ptx, pty + 30 * (4 * num + 1)); drawText = strDescriptionMargin; g.DrawString(drawText, drawFont, drawBrush, ptx, pty + 30 * (4 * num + 2)); drawText = strDescriptionOrientation; g.DrawString(drawText, drawFont, drawBrush, ptx, pty + 30 * (4 * num + 3)); drawText = strDescriptionBound; g.DrawString(drawText, drawFont, drawBrush, ptx, pty + 30 * (4 * num + 4)); // drawText = num.ToString(); g.DrawString(drawText, drawFont, drawBrush, axisH[0].X, axisH[0].Y); num++; } } g.Dispose(); } string name = newPath + "\\" + imageName + ".jpg"; dstimage.Save(name, System.Drawing.Imaging.ImageFormat.Png); dstimage.Dispose(); } } } } public void Save(Bitmap image, int imageId, string imageName) { string currentPath = System.Environment.CurrentDirectory; string newPath = System.IO.Path.Combine(currentPath, "result"); System.IO.Directory.CreateDirectory(newPath); int imgNum = _allImages.Count; if (image == null || _allImages.Count <= 0) { return; } if (_allImages[imageId].Lesions.Count <= 0) { string name = newPath + "\\" + imageName + ".png"; //image.Save(name, System.Drawing.Imaging.ImageFormat.Png); } else { int numLesions = _allImages[imageId].Lesions.Count; Bitmap origImg = image; for (int jj = 0; jj < numLesions; jj++) { EnumDesEchoPatternValue echoGT = _allImages[imageId].Lesions[jj].EchoPattern; EnumDesShapeValue shapeGT = _allImages[imageId].Lesions[jj].Shape; EnumDesMarginValue marginGT = _allImages[imageId].Lesions[jj].Margin; EnumDesOrientationValue orientationGT = _allImages[imageId].Lesions[jj].Orientation; EnumDesLesionBoundaryValue boundGT = _allImages[imageId].Lesions[jj].Boundary; string echo = null, shape = null, margin = null, orientation = null, bound = null; switch (echoGT) { case EnumDesEchoPatternValue.Anechoic: echo = "无回声"; break; case EnumDesEchoPatternValue.Hypoechoic: echo = "低回声"; break; case EnumDesEchoPatternValue.Hyperechoic: echo = "高回声"; break; case EnumDesEchoPatternValue.Strongechoic: echo = "强回声"; break; case EnumDesEchoPatternValue.Complex: echo = "混合回声"; break; case EnumDesEchoPatternValue.Isoechoic: echo = "等回声"; break; } switch (shapeGT) { case EnumDesShapeValue.Oval: shape = "椭圆形"; break; case EnumDesShapeValue.Round: shape = "圆形"; break; case EnumDesShapeValue.Irregular: shape = "不规则"; break; } switch (marginGT) { case EnumDesMarginValue.Circumscribed: margin = "光整"; break; case EnumDesMarginValue.NonCircumscribed: margin = "不光整"; break; } switch (orientationGT) { case EnumDesOrientationValue.Parallel: orientation = "平行"; break; case EnumDesOrientationValue.NonParallel: orientation = "非平行"; break; } switch (boundGT) { case EnumDesLesionBoundaryValue.AbruptInterface: bound = "清晰"; break; case EnumDesLesionBoundaryValue.EchogenicHalo: bound = "模糊"; break; } // 显示新的病灶 LesionInfo lesion = _allImages[imageId].Lesions[jj]; int num2 = lesion.Contour.Count; using (var g = Graphics.FromImage(origImg)) { System.Drawing.Pen pen3 = new System.Drawing.Pen(System.Drawing.Brushes.Navy, 2); System.Drawing.PointF[] lesionContour = new PointF[num2]; for (int i = 0; i < num2; i++) { lesionContour[i].X = _allImages[imageId].Lesions[jj].Contour[i].X; lesionContour[i].Y = _allImages[imageId].Lesions[jj].Contour[i].Y; } if (num2 > 0) { System.Drawing.Pen pen = new System.Drawing.Pen(System.Drawing.Brushes.Orange, 2); g.DrawLines(pen, lesionContour); //画病灶轮廓 pen.Dispose(); } System.Drawing.PointF[] axisH = new PointF[2]; System.Drawing.PointF[] axisV = new PointF[2]; axisH[0].X = lesion.HorizontalPoint1.X; axisH[0].Y = lesion.HorizontalPoint1.Y; axisH[1].X = lesion.HorizontalPoint2.X; axisH[1].Y = lesion.HorizontalPoint2.Y; axisV[0].X = lesion.VerticalPoint1.X; axisV[0].Y = lesion.VerticalPoint1.Y; axisV[1].X = lesion.VerticalPoint2.X; axisV[1].Y = lesion.VerticalPoint2.Y; //画轮廓的长短轴 System.Drawing.Pen pen_h = new System.Drawing.Pen(System.Drawing.Brushes.PaleGreen, 2); g.DrawLines(pen_h, axisH); //横轴,浅绿色 System.Drawing.Pen pen_v = new System.Drawing.Pen(System.Drawing.Brushes.Red, 1); g.DrawLines(pen_v, axisV); //纵轴,红色 //写汉字 Font drawFont = new Font("黑体", 24); SolidBrush drawBrush = new SolidBrush(System.Drawing.Color.GreenYellow); float x = 10.0f; float y = 0.0f + 20; string drawText = echo;// g.DrawString(drawText, drawFont, drawBrush, x, y + 30 * 4 * jj); drawText = shape; g.DrawString(drawText, drawFont, drawBrush, x, y + 30 * (4 * jj + 1)); drawText = margin; g.DrawString(drawText, drawFont, drawBrush, x, y + 30 * (4 * jj + 2)); drawText = orientation; g.DrawString(drawText, drawFont, drawBrush, x, y + 30 * (4 * jj + 3)); drawText = bound; g.DrawString(drawText, drawFont, drawBrush, x, y + 30 * (4 * jj + 4)); // drawText = jj.ToString(); g.DrawString(drawText, drawFont, drawBrush, axisH[0].X, axisH[0].Y); g.Dispose(); } } string name = newPath + "\\" + imageName + ".png"; origImg.Save(name, System.Drawing.Imaging.ImageFormat.Png); origImg.Dispose(); } } private void OnBtnGoBackClicked(object sender, RoutedEventArgs e) { int num = _drawingPoints.Count; if (num > 0) { _drawingPoints.RemoveAt(num - 1); DrawContourInCanvas(_drawingPoints, EnumCanvasItemType.Drawing, "drawingPt"); } else { System.Windows.MessageBox.Show("轮廓点不存在"); } //UpdateLesionsInCanvas(); ////_drawingPoints.Add(_drawingPoints[0]); //List contourInOrigImg = new List(); //foreach (var point in _drawingPoints) //{ // contourInOrigImg.Add(GetPosInOrigImage(point)); //} //_drawingPoints = new List(); //_mouseOper = EnumMouseOperType.None; //RemoveContourInCanvas("drawing"); //UserControlLesionSelected.SetContour(contourInOrigImg); } } }