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 Rect = AI.Common.Interface.Rect; namespace YOLOInstanceSegDemo { 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 } }