using System;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Controls;
using AI.Common;
using Rectangle = System.Drawing.Rectangle;
using RUSInferNet;
using HumanOrganSegDemo;
using RUSInferNet.PostProcess;
using System.Xml.Linq;
using System.Windows.Media;
using System.Linq;
namespace HumanOrganSegmentDemo
{
public class TestResults
{
///
/// 人体/人脸
///
public Dictionary BodyPartBoundBoxes;
///
/// 一张图里目标对象的关键点
///
public BodyKeyPoints BodyKeyPoints { get; set; }
///
/// 目标脏器的轮廓信息
///
public ContourPoints OrganContours;
///
/// 像素坐标系下人体朝向的方向向量
///
public Point2D HumanOrientationInPCS { get; set; }
public TestResults(Dictionary bodyBoundBoxes, BodyKeyPoints bodyKeyPoints, ContourPoints organContours, Point2D humanOrientationInPCS)
{
BodyPartBoundBoxes = bodyBoundBoxes;
BodyKeyPoints = bodyKeyPoints;
OrganContours = organContours;
HumanOrientationInPCS = humanOrientationInPCS;
}
}
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);
}
}
///
/// ImageInfo.xaml 的交互逻辑
///
public partial class ImageCanvas : UserControl
{
#region private
private Bitmap _image;
//private volatile bool _enableAI;
private volatile bool _showContour;
private volatile bool _showSize;
private MyTransform _transform;
private TestResults _testResult;
#endregion
#region properties
public Bitmap Image { get => _image; }
#endregion
#region 用户界面响应
private void OcardialSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
{
UpdateTransforms();
}
#endregion
#region public
public ImageCanvas()
{
InitializeComponent();
}
public void UpdateImage(Bitmap image)
{
if (_image != null)
{
_image.Dispose();
}
_image = image.Clone(new 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 UpdateHumanDetectResults(HumanDetectResultPerImage result)
{
_testResult = new TestResults(result.BodyPartBoundBoxesAll, result.ObjectKeyPoints, result.ObjectOrganContours, result.ObjectOrientationInPCS);
UpdateTestResultShow();
}
public void UpdateRoughPathResults(Point2D[] pathPts)
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
DrawContoursInCanvas(pathPts, "path", System.Windows.Media.Brushes.Cyan);
}));
}
public void Clear()
{
// 清空画布上的所有内容
TestResultCanvas.Children.Clear();
}
#endregion
#region private
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;
}
private void UpdateTransforms()
{
if (_image != null)
{
// 使图片保持长宽比例,居中显示,需要平移和缩放
var imgWidth = _image.Width;
var imgHeight = _image.Height;
var ocardialWidth = TestResultCanvas.ActualWidth;
var ocardialHeight = TestResultCanvas.ActualHeight;
var scaleX = ocardialWidth / imgWidth;
var scaleY = ocardialHeight / 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 UpdateTestResultShow()
{
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>
{
// 清空画布上的所有内容
TestResultCanvas.Children.Clear();
// 没有结果就直接返回
if (_testResult == null)
{
return;
}
if(_testResult.BodyPartBoundBoxes.Count==0)
{
return;
}
if (_testResult.BodyPartBoundBoxes.Count > 0)
{
// 更新所有框
foreach (var rcs in _testResult.BodyPartBoundBoxes.ToArray())
{
if (rcs.Key == EnumHumanParts.Head)
{
DrawRectsInCanvas(rcs.Value, "head");
}
if (rcs.Key == EnumHumanParts.Body)
{
DrawRectsInCanvas(rcs.Value, "body");
}
}
}
// 更新人体关键点
DrawHumanInCanvas(_testResult.BodyKeyPoints, "keyPts");
// 更新轮廓
DrawContoursInCanvas(_testResult.OrganContours.Points, "contours", System.Windows.Media.Brushes.OrangeRed);
// 更新人体朝向
//if (_testResult.HumanOrientationInPCS.X * _testResult.HumanOrientationInPCS.Y != 0)
//{
// Point2D[] pts = new Point2D[2];
// pts[0] = new Point2D(_image.Width / 2, _image.Height / 2);
// pts[1] = new Point2D(pts[0].X + _testResult.HumanOrientationInPCS.X, pts[0].Y + _testResult.HumanOrientationInPCS.Y);
// DrawContoursInCanvas(pts, "Orientation", System.Windows.Media.Brushes.BlueViolet);
//}
}));
}
///
/// 从画布上移除矩形框
///
///
private void RemoveRectsCanvas(string roiName)
{
// 框
string textName = roiName;
List rcsExist = TestResultCanvas.FindName(textName) as List;
if (rcsExist != null)
{
foreach (var rcExist in rcsExist)
{
TestResultCanvas.Children.Remove(rcExist);
}
TestResultCanvas.UnregisterName(textName);
}
}
///
/// 在画布上画出矩形框
///
///
///
private void DrawRectsInCanvas(Rect[] rcs, string rcName)
{
if (_transform == null)
{
return;
}
// 已有则删除
RemoveRectsCanvas(rcName);
List rcRenders = new List { };
foreach (var rc in rcs)
{
System.Windows.Shapes.Rectangle rcRender = new System.Windows.Shapes.Rectangle();
rcRender.StrokeThickness = 3;
rcRender.Stroke = System.Windows.Media.Brushes.AliceBlue;
var transPtLeftTop = _transform.Transform(new System.Windows.Point(rc.Left, rc.Top));
var transPtRightDown = _transform.Transform(new System.Windows.Point(rc.Left + rc.Width, rc.Top + rc.Height));
Canvas.SetLeft(rcRender, transPtLeftTop.X);
Canvas.SetTop(rcRender, transPtLeftTop.Y);
rcRender.Width = transPtRightDown.X - transPtLeftTop.X;
rcRender.Height = transPtRightDown.Y - transPtLeftTop.Y;
TestResultCanvas.Children.Add(rcRender);
//TestResultCanvas.RegisterName(rcName, rcRender);
rcRenders.Add(rcRender);
}
TestResultCanvas.RegisterName(rcName, rcRenders);
}
///
/// 在画布上画出轮廓
///
///
///
private void DrawContoursInCanvas(Point2D[] pts, string registerName, System.Windows.Media.Brush color)
{
if (_transform == null)
{
return;
}
// 已有则删除
RemoveContoursInCanvas(registerName);
if(pts== null)
{
return;
}
PointCollection contourPoints = new PointCollection();
foreach (var pt in pts)
{
var point = new System.Windows.Point(pt.X, pt.Y);
var transPoint = _transform.Transform(point);
contourPoints.Add(transPoint);
}
System.Windows.Shapes.Polyline contourDraw = new System.Windows.Shapes.Polyline();
contourDraw.Points = contourPoints;
contourDraw.StrokeThickness = 3;
contourDraw.Stroke = color;
TestResultCanvas.Children.Add(contourDraw);
TestResultCanvas.RegisterName(registerName, contourDraw);
}
///
/// 从画布上将轮廓移除
///
///
private void RemoveContoursInCanvas(string registerName)
{
System.Windows.Shapes.Polyline contourExist = TestResultCanvas.FindName(registerName) as System.Windows.Shapes.Polyline;
if (contourExist != null)
{
TestResultCanvas.Children.Remove(contourExist);
TestResultCanvas.UnregisterName(registerName);
}
}
private void DrawHumanInCanvas(BodyKeyPoints humanKeyPts, string name)
{
if (_transform == null)
{
return;
}
// 已有则删除
RemoveHumanInCanvas(name);
var neckPosition = _transform.Transform(new System.Windows.Point(humanKeyPts.Neck.X, humanKeyPts.Neck.Y));
var leftShoulderPosition = _transform.Transform(new System.Windows.Point(humanKeyPts.LeftShoulder.X, humanKeyPts.LeftShoulder.Y));
var rightShoulderPosition = _transform.Transform(new System.Windows.Point(humanKeyPts.RightShoulder.X, humanKeyPts.RightShoulder.Y));
// 脖子
if (humanKeyPts.Neck.X * humanKeyPts.Neck.Y > 0)
{
System.Windows.Shapes.Ellipse neck = new System.Windows.Shapes.Ellipse();
neck.StrokeThickness = 4;
neck.Stroke = System.Windows.Media.Brushes.Orange;
neck.Width = 6;
Canvas.SetLeft(neck, neckPosition.X);
Canvas.SetTop(neck, neckPosition.Y);
TestResultCanvas.Children.Add(neck);
string neckName = "Human_" + name + "_point_head";
TestResultCanvas.RegisterName(neckName, neck);
}
// 左肩
if (humanKeyPts.LeftShoulder.X * humanKeyPts.LeftShoulder.Y > 0)
{
System.Windows.Shapes.Ellipse leftShoulder = new System.Windows.Shapes.Ellipse();
leftShoulder.StrokeThickness = 3;
leftShoulder.Stroke = System.Windows.Media.Brushes.AliceBlue;
leftShoulder.Width = 6;
Canvas.SetLeft(leftShoulder, leftShoulderPosition.X);
Canvas.SetTop(leftShoulder, leftShoulderPosition.Y);
TestResultCanvas.Children.Add(leftShoulder);
string leftShoulderName = "Human_" + name + "_point_leftShoulder";
TestResultCanvas.RegisterName(leftShoulderName, leftShoulder);
}
// 右肩
if (humanKeyPts.RightShoulder.X * humanKeyPts.RightShoulder.Y > 0)
{
System.Windows.Shapes.Ellipse rightShoulder = new System.Windows.Shapes.Ellipse();
rightShoulder.StrokeThickness = 3;
rightShoulder.Stroke = System.Windows.Media.Brushes.AliceBlue;
rightShoulder.Width = 6;
Canvas.SetLeft(rightShoulder, rightShoulderPosition.X);
Canvas.SetTop(rightShoulder, rightShoulderPosition.Y);
TestResultCanvas.Children.Add(rightShoulder);
string rightShoulderName = "Human_" + name + "_point_rightShoulder";
TestResultCanvas.RegisterName(rightShoulderName, rightShoulder);
}
// 从脖子到左肩的线
if (humanKeyPts.Neck.X * humanKeyPts.Neck.Y > 0 && humanKeyPts.LeftShoulder.X * humanKeyPts.LeftShoulder.Y > 0)
{
System.Windows.Shapes.Line lineLeft = new System.Windows.Shapes.Line();
lineLeft.StrokeThickness = 2;
lineLeft.Stroke = System.Windows.Media.Brushes.RosyBrown;
lineLeft.X1 = neckPosition.X;
lineLeft.Y1 = neckPosition.Y;
lineLeft.X2 = leftShoulderPosition.X;
lineLeft.Y2 = leftShoulderPosition.Y;
TestResultCanvas.Children.Add(lineLeft);
string lineLeftName = "Human_" + name + "_lineLeft";
TestResultCanvas.RegisterName(lineLeftName, lineLeft);
}
// 从脖子到右肩的线
if (humanKeyPts.Neck.X * humanKeyPts.Neck.Y > 0 && humanKeyPts.RightShoulder.X * humanKeyPts.RightShoulder.Y > 0)
{
System.Windows.Shapes.Line lineRight = new System.Windows.Shapes.Line();
lineRight.StrokeThickness = 2;
lineRight.Stroke = System.Windows.Media.Brushes.DarkGray;
lineRight.X1 = neckPosition.X;
lineRight.Y1 = neckPosition.Y;
lineRight.X2 = rightShoulderPosition.X;
lineRight.Y2 = rightShoulderPosition.Y;
TestResultCanvas.Children.Add(lineRight);
string lineRightName = "Human_" + name + "_lineRight";
TestResultCanvas.RegisterName(lineRightName, lineRight);
}
}
private void RemoveHumanInCanvas(string name)
{
// 脖子
string neckName = "Human_" + name + "_point_head";
System.Windows.Shapes.Ellipse neck = TestResultCanvas.FindName(neckName) as System.Windows.Shapes.Ellipse;
if (neck != null)
{
TestResultCanvas.Children.Remove(neck);
TestResultCanvas.UnregisterName(neckName);
}
// 左肩
string leftShoulderName = "Human_" + name + "_point_leftShoulder";
System.Windows.Shapes.Ellipse leftShoulder = TestResultCanvas.FindName(leftShoulderName) as System.Windows.Shapes.Ellipse;
if (leftShoulder != null)
{
TestResultCanvas.Children.Remove(leftShoulder);
TestResultCanvas.UnregisterName(leftShoulderName);
}
// 右肩
string rightShoulderName = "Human_" + name + "_point_rightShoulder";
System.Windows.Shapes.Ellipse rightShoulder = TestResultCanvas.FindName(rightShoulderName) as System.Windows.Shapes.Ellipse;
if (rightShoulder != null)
{
TestResultCanvas.Children.Remove(rightShoulder);
TestResultCanvas.UnregisterName(rightShoulderName);
}
// 从脖子到左肩的线
string lineLeftName = "Human_" + name + "_lineLeft";
System.Windows.Shapes.Line lineLeft = TestResultCanvas.FindName(lineLeftName) as System.Windows.Shapes.Line;
if (lineLeft != null)
{
TestResultCanvas.Children.Remove(lineLeft);
TestResultCanvas.UnregisterName(lineLeftName);
}
// 从脖子到右肩的线
string lineRightName = "Human_" + name + "_lineRight";
System.Windows.Shapes.Line lineRight = TestResultCanvas.FindName(lineRightName) as System.Windows.Shapes.Line;
if (lineRight != null)
{
TestResultCanvas.Children.Remove(lineRight);
TestResultCanvas.UnregisterName(lineRightName);
}
}
#endregion
}
}