using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Threading;
using System.Windows.Media.Imaging;
using System.Drawing;
using System.Drawing.Imaging;
using YOLODetectProcessLib;
namespace YOLODetectDemo
{
public class Roi
{
public Rect BoundBox { get; set; }
public System.Windows.Media.Brush Color { get; set; }
public string LabelName { get; set; }
}
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
private Bitmap _image;
private List _rois;
private volatile bool _enableAI;
private volatile bool _showContour;
private volatile bool _showSize;
private MyTransform _transform;
#endregion
#region properties
public Bitmap Image { get => _image; }
#endregion
#region 用户界面响应
private void CanvasSizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
{
UpdateTransforms();
}
#endregion
#region public
public ImageCanvas()
{
InitializeComponent();
}
public void SetShowParams(bool enableAI)
{
_enableAI = enableAI;
if (_rois != null)
{
for (int ni = 0; ni < _rois.Count; ni++)
{
DrawRoiInCanvas(_rois[ni], ni.ToString());
}
}
}
public void UpdateImage(Bitmap image)
{
_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;
}));
}
#endregion
#region private
private void RemoveRoiInCanvas(string roiName)
{
// 文字
string textName = "Text_" + roiName;
System.Windows.Controls.TextBlock textExist = RoiCanvas.FindName(textName) as System.Windows.Controls.TextBlock;
if (textExist != null)
{
RoiCanvas.Children.Remove(textExist);
RoiCanvas.UnregisterName(textName);
}
}
private void DrawRoiInCanvas(Roi roi, string roiName)
{
if (_transform == null)
{
return;
}
// 已有则删除
RemoveRoiInCanvas(roiName);
// 不启用AI,则直接退出
if (!_enableAI)
{
return;
}
// 将Roi的序号写在左上角
var pointLT = new System.Windows.Point(roi.BoundBox.Left, roi.BoundBox.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);
RoiCanvas.Children.Add(text);
string textName = "Text_" + roiName;
RoiCanvas.RegisterName(textName, text);
}
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 canvasWidth = RoiCanvas.ActualWidth;
var canvasHeight = RoiCanvas.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);
}
}
#endregion
}
}