using AI.Common;
using UsHepatoRenalRatioDetectLib;
using UsHepatoRenalRatioDetectLib.OrganSegProcessModule;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using static System.Net.Mime.MediaTypeNames;
using Rect = AI.Common.Rect;
namespace HepatoRenalEchoContrastDemo
{
//public class TestResults
//{
// public Point2D[][] Countours { get; set; }
// public Rect[] Rois { get; set; }
// public double EchoContastValue { get; set; }
// public TestResults(Point2D[][] countours, Rect[] rois, double echoContastValue)
// {
// Countours = countours;
// Rois = rois;
// EchoContastValue = echoContastValue;
// }
//}
public class RoiInfo
{
public Rect RoiRect { get; set; }
public System.Windows.Media.Brush Color { get; set; }
public RoiInfo(Rect roi, System.Windows.Media.Brush color)
{
RoiRect = roi;
Color = color;
}
}
public class OrganInfo
{
public string OrganName { get; set; }
public Rect BoundingBox { get; set; }
public Point2D[][] Contours { get; set; }
public System.Windows.Media.Brush Color => System.Windows.Media.Brushes.Green;
public OrganInfo(string organName, Rect boundingBox, Point2D[][] contours)
{
OrganName = organName;
BoundingBox = boundingBox;
Contours = contours;
}
}
public class MyTransform
{
public double Scale { get; set; }
public double OffsetX { get; set; }
public double OffsetY { get; set; }
public MyTransform(double scale, double offsetX, double offsetY)
{
Scale = scale;
OffsetX = offsetX;
OffsetY = offsetY;
}
public System.Windows.Point Transform(System.Windows.Point point)
{
double x = OffsetX + Scale * point.X;
double y = OffsetY + Scale * point.Y;
return new System.Windows.Point(x, y);
}
public System.Windows.Rect Transform(System.Windows.Rect rect)
{
double left = OffsetX + Scale * rect.Left;
double top = OffsetY + Scale * rect.Top;
double width = Scale * rect.Width;
double height = Scale * rect.Height;
return new System.Windows.Rect(left, top, width, height);
}
}
///
/// ImageCanvas.xaml 的交互逻辑
///
public partial class ImageCanvas : UserControl
{
#region private variables
private Bitmap _image;
private List _rois;
private List _organs;
private volatile bool _showOrgan;
private volatile bool _showRois;
private volatile bool _showEchoContastValue;
private MyTransform _transform;
private double _echoContrastRatio;
#endregion
#region 用户界面响应
private void CanvasSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
{
UpdateTransforms();
}
#endregion
#region public funcs
public ImageCanvas()
{
InitializeComponent();
}
///
/// 设置显示参数
///
///
///
///
public void SetShowParams(bool showCountours, bool showRois, bool showeEchoContastValue)
{
_showOrgan = showCountours;
_showRois = showRois;
_showEchoContastValue = showeEchoContastValue;
if (_rois != null)
{
UpdateRois();
}
if (_organs != null)
{
UpdateOrgans();
}
}
public void UpdateImage(Bitmap image)
{
if (_image != null)
{
_image.Dispose();
}
_image = image.Clone(new System.Drawing.Rectangle(0, 0, image.Width, image.Height), image.PixelFormat);
// 更新缩放比例
UpdateTransforms();
// 更新图像显示
var bitmapImage = BitmapToBitmapImage(image);
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
ImageShow.Source = bitmapImage;
}));
}
public void UpdateTestResults(HRRDetectResultPerImg detectedResult)
{
List organs = new List();
List rois = new List();
foreach (var organ in detectedResult.SegResults)
{
organs.Add(new OrganInfo(organ.Organ.ToString(), organ.BoundingBox, organ.Contours));
}
foreach (var roiDict in detectedResult.Rois)
{
rois.Add(new RoiInfo(roiDict.Value, System.Windows.Media.Brushes.Yellow));
}
// 删掉旧的Roi和Organ
RemoveRois();
RemoveOrgans();
RemoveText();
_organs = organs;
_rois = rois;
_echoContrastRatio = detectedResult.HepatoRenalRatio;
// 更新画布上显示的Roi和Organ
////////////////////////////////
double ratio = Math.Round(_echoContrastRatio, 4);
if (ratio > 0)
{
UpdateRois();
}
///////////////////////////////
UpdateOrgans();
UpdateText();
}
public void ClearTestResult()
{
// 删掉旧的Roi和Organ
RemoveRois();
RemoveOrgans();
RemoveText();
// 设置
_rois = null;
_organs = null;
}
///
/// 将画布上的点转到图像坐标系下
///
///
///
public Point2D TransBack(System.Windows.Point point)
{
int x = Convert.ToInt32((point.X - _transform.OffsetX) / _transform.Scale);
int y = Convert.ToInt32((point.Y - _transform.OffsetY) / _transform.Scale);
return new Point2D(x, y);
}
#endregion
#region private funcs
private BitmapImage BitmapToBitmapImage(Bitmap img)
{
BitmapImage bmpimg = new BitmapImage();
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
img.Save(ms, ImageFormat.Png);
bmpimg.BeginInit();
bmpimg.StreamSource = ms;
bmpimg.CacheOption = BitmapCacheOption.OnLoad;
bmpimg.EndInit();
bmpimg.Freeze();
ms.Dispose();
}
return bmpimg;
}
public void RemoveRoiInCanvas(string roiName)
{
// 框
string rectName = "ROI_Rect_" + roiName;
System.Windows.Shapes.Rectangle rectExist = TestResultCanvas.FindName(rectName) as System.Windows.Shapes.Rectangle;
if (rectExist != null)
{
TestResultCanvas.Children.Remove(rectExist);
TestResultCanvas.UnregisterName(rectName);
}
// 文字
string textName = "ROI_Text_" + roiName;
System.Windows.Controls.TextBlock textExist = TestResultCanvas.FindName(textName) as System.Windows.Controls.TextBlock;
if (textExist != null)
{
TestResultCanvas.Children.Remove(textExist);
TestResultCanvas.UnregisterName(textName);
}
}
private void RemoveOrganInCanvas(OrganInfo organ)
{
string organName = organ.OrganName;
// 框
string rectName = "Organ_Rect_" + organName;
System.Windows.Shapes.Rectangle rectExist = TestResultCanvas.FindName(rectName) as System.Windows.Shapes.Rectangle;
if (rectExist != null)
{
TestResultCanvas.Children.Remove(rectExist);
TestResultCanvas.UnregisterName(rectName);
}
// 轮廓
int count = organ.Contours.Length;
for (int ni = 0; ni < count; ni++)
{
string contourName = "Organ_Contour_" + organName + "_" + ni;
System.Windows.Shapes.Polygon contourExist = TestResultCanvas.FindName(contourName) as System.Windows.Shapes.Polygon;
if (contourExist != null)
{
TestResultCanvas.Children.Remove(contourExist);
TestResultCanvas.UnregisterName(contourName);
}
}
// 文字
string textName = "Organ_Text_" + organName;
System.Windows.Controls.TextBlock textExist = TestResultCanvas.FindName(textName) as System.Windows.Controls.TextBlock;
if (textExist != null)
{
TestResultCanvas.Children.Remove(textExist);
TestResultCanvas.UnregisterName(textName);
}
}
public void DrawRoiInCanvas(RoiInfo roi, string roiName)
{
if (_transform == null)
{
return;
}
// 已有则删除
RemoveRoiInCanvas(roiName);
// 不显示ROI,则直接退出
if (!_showRois)
{
return;
}
// 画框
var rect = new System.Windows.Rect(roi.RoiRect.Left, roi.RoiRect.Top, roi.RoiRect.Width, roi.RoiRect.Height);
var transRect = _transform.Transform(rect);
System.Windows.Shapes.Rectangle rectDraw = new System.Windows.Shapes.Rectangle();
rectDraw.StrokeThickness = 3;
rectDraw.Stroke = roi.Color;
rectDraw.Width = transRect.Width;
rectDraw.Height = transRect.Height;
Canvas.SetLeft(rectDraw, transRect.Left);
Canvas.SetTop(rectDraw, transRect.Top);
TestResultCanvas.Children.Add(rectDraw);
string rectName = "ROI_Rect_" + roiName;
TestResultCanvas.RegisterName(rectName, rectDraw);
// 将Roi的序号写在左上角
var pointLT = new System.Windows.Point(roi.RoiRect.Left, roi.RoiRect.Top);
var transPointLT = _transform.Transform(pointLT);
var textLeft = transPointLT.X - 16;
var textTop = transPointLT.Y;
TextBlock text = new TextBlock();
text.Text = roiName;
text.FontSize = 16;
text.FontWeight = System.Windows.FontWeights.Bold;
text.Foreground = roi.Color;
text.VerticalAlignment = System.Windows.VerticalAlignment.Top;
Canvas.SetLeft(text, textLeft);
Canvas.SetTop(text, textTop);
TestResultCanvas.Children.Add(text);
string textName = "ROI_Text_" + roiName;
TestResultCanvas.RegisterName(textName, text);
}
private void DrawOrganInCanvas(OrganInfo organ)
{
if (_transform == null)
{
return;
}
// 已有则删除
RemoveOrganInCanvas(organ);
// 是否显示Organ
if (!_showOrgan)
{
return;
}
// 有轮廓就显示轮廓,没有轮廓就显示方框
string organName = organ.OrganName;
if (organ.Contours.Length > 0)
{
int count = organ.Contours.Length;
for (int ni = 0; ni < count; ni++)
{
Point2D[] contour = organ.Contours[ni];
PointCollection contourPoints = new PointCollection();
for (int nj = 0; nj < contour.Length; nj++)
{
var point = new System.Windows.Point(contour[nj].X, contour[nj].Y);
var transPoint = _transform.Transform(point);
contourPoints.Add(transPoint);
}
System.Windows.Shapes.Polygon contourDraw = new System.Windows.Shapes.Polygon();
contourDraw.Points = contourPoints;
contourDraw.StrokeThickness = 3;
contourDraw.Stroke = organ.Color;
TestResultCanvas.Children.Add(contourDraw);
string contourName = "Organ_Contour_" + organName + "_" + ni;
TestResultCanvas.RegisterName(contourName, contourDraw);
}
}
else
{
var rect = new System.Windows.Rect(organ.BoundingBox.Left, organ.BoundingBox.Top, organ.BoundingBox.Width, organ.BoundingBox.Height);
var transRect = _transform.Transform(rect);
System.Windows.Shapes.Rectangle rectDraw = new System.Windows.Shapes.Rectangle();
rectDraw.StrokeThickness = 3;
rectDraw.Stroke = organ.Color;
rectDraw.Width = transRect.Width;
rectDraw.Height = transRect.Height;
Canvas.SetLeft(rectDraw, transRect.Left);
Canvas.SetTop(rectDraw, transRect.Top);
TestResultCanvas.Children.Add(rectDraw);
string rectName = "Organ_Rect_" + organName;
TestResultCanvas.RegisterName(rectName, rectDraw);
}
// 将Organ的序号写在左上角
var pointLT = new System.Windows.Point(organ.BoundingBox.Left, organ.BoundingBox.Top);
var transPointLT = _transform.Transform(pointLT);
var textLeft = transPointLT.X + 16;
var textTop = transPointLT.Y;
TextBlock text = new TextBlock();
text.Text = organName;
text.FontSize = 16;
text.FontWeight = System.Windows.FontWeights.Bold;
text.Foreground = organ.Color;
text.VerticalAlignment = System.Windows.VerticalAlignment.Top;
Canvas.SetLeft(text, textLeft);
Canvas.SetTop(text, textTop);
TestResultCanvas.Children.Add(text);
string textName = "Organ_Text_" + organName;
TestResultCanvas.RegisterName(textName, text);
}
private void UpdateTransforms()
{
if (_image != null)
{
// 使图片保持长宽比例,居中显示,需要平移和缩放
var imgWidth = _image.Width;
var imgHeight = _image.Height;
var canvasWidth = TestResultCanvas.ActualWidth;
var canvasHeight = TestResultCanvas.ActualHeight;
var scaleX = canvasWidth / imgWidth;
var scaleY = canvasHeight / imgHeight;
var scale = scaleX < scaleY ? scaleX : scaleY;
double offsetX, offsetY;
if (Math.Abs(scale - scaleX) < 0.0001)
{
offsetY = 0.5 * (scaleY - scale) * imgHeight;
offsetX = 0;
}
else
{
offsetX = 0.5 * (scaleX - scale) * imgWidth;
offsetY = 0;
}
_transform = new MyTransform(scale, offsetX, offsetY);
}
}
private void RemoveRois()
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
// 移除所有旧的ROI
if (_rois != null)
{
for (int ni = 0; ni < _rois.Count; ni++)
{
RemoveRoiInCanvas(ni.ToString());
}
}
}));
}
private void RemoveOrgans()
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
// 移除所有旧的Organ
if (_organs != null)
{
for (int ni = 0; ni < _organs.Count; ni++)
{
RemoveOrganInCanvas(_organs[ni]);
}
}
}));
}
private void RemoveText()
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
// 文字
string textName = "Ratio";
System.Windows.Controls.TextBlock textExist = TestResultCanvas.FindName(textName) as System.Windows.Controls.TextBlock;
if (textExist != null)
{
TestResultCanvas.Children.Remove(textExist);
TestResultCanvas.UnregisterName(textName);
}
}));
}
private void UpdateRois()
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
if (_rois != null)
{
for (int ni = 0; ni < _rois.Count; ni++)
{
DrawRoiInCanvas(_rois[ni], ni.ToString());
}
}
}));
}
private void UpdateOrgans()
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
if (_organs != null)
{
for (int ni = 0; ni < _organs.Count; ni++)
{
DrawOrganInCanvas(_organs[ni]);
}
}
}));
}
private void UpdateText()
{
Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
if (_transform == null)
{
return;
}
// 已有则删除
RemoveText();
// 不显示ROI,则直接退出
if (!_showRois)
{
return;
}
var pointLT = new System.Windows.Point(50, 50);
var transPointLT = _transform.Transform(pointLT);
var textLeft = transPointLT.X - 16;
var textTop = transPointLT.Y;
TextBlock text = new TextBlock();
double ratio = Math.Round(_echoContrastRatio, 4);
text.Text = ratio.ToString();
if (ratio<=0)
{
text.Text = "Invalid !";
}
text.FontSize = 30;
text.FontWeight = System.Windows.FontWeights.Bold;
text.Foreground = System.Windows.Media.Brushes.Yellow;
text.VerticalAlignment = System.Windows.VerticalAlignment.Top;
Canvas.SetLeft(text, textLeft);
Canvas.SetTop(text, textTop);
TestResultCanvas.Children.Add(text);
string textName = "Ratio";
TestResultCanvas.RegisterName(textName, text);
}));
}
#endregion
}
}