图像标注代码示例
我们在PageLight页面上实现该功能
第一步,PageLight.xaml添加以下代码
<Page x:Class="wpfbase.PageLight"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:wpfbase"
mc:Ignorable="d"
d:DesignHeight="325" d:DesignWidth="525"
Title="PageLight">
<Page.Resources >
<!-- 定义一个key=PointEllipseStyle的Ellipse样式 -->
<Style TargetType="Ellipse" x:Key="PointEllipseStyle">
<Style.Setters>
<Setter Property="Width" Value="0" />
<Setter Property="Height" Value="9" />
<Setter Property="Fill" Value="Blue" />
</Style.Setters>
<!-- FileButtonStyle样式触发器 -->
<Style.Triggers>
<!-- 鼠标移过时触发 -->
<Trigger Property="Control.IsMouseOver" Value="True">
<Setter Property="Fill" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="5"/>
<RowDefinition Height="*"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="5*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal">
<Button Content="矩形标注" Click="LabelRectangle" Name="button_rectangle" Focusable="False"/>
<Button Content="取消选中" Click="SelectCancel" Focusable="False"/>
</StackPanel>
<ListBox Name="labelbox" Grid.Row="2" Grid.Column="0"
SelectionChanged="SelectChange" KeyDown="LabelboxKeyResponse"/>
<Grid Name="workspace" Grid.Row="2" Grid.Column="1" Background="Black"
MouseLeftButtonDown="ImgMouseLeftButtonDown"
MouseLeftButtonUp="ImgMouseLeftButtonUp"
MouseRightButtonDown="ImgMouseRightButtonDown"
MouseRightButtonUp="ImgMouseRightButtonUp"
MouseMove="ImgMouseMove"
MouseWheel="ImgMouseWheel"
MouseLeave="ImgMouseLeave">
<Grid.Resources>
<TransformGroup x:Key="Imageview">
<ScaleTransform/>
<TranslateTransform/>
</TransformGroup>
</Grid.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled"
Focusable="False" x:Name="BackFrame">
<ContentControl Name="imgcontrol">
<Image Name="image" Source="F:\chenggeng\source\Image\Desert.jpg"
Width="Auto" Height="Auto" RenderTransform="{StaticResource Imageview}"
Stretch="Uniform" RenderOptions.BitmapScalingMode="NearestNeighbor"/>
</ContentControl>
</ScrollViewer>
<Path Stroke="Blue" Name="crossline"></Path>
<Rectangle Name="rectanglebox" Stroke="#00ff00" Fill="#5588ffcc" Width="0" Height="0"/>
<Ellipse Name="c1" Tag="1" Style="{StaticResource PointEllipseStyle}"
MouseDown="PointMouseDown" MouseMove="PointMouseMove" MouseUp="PointMouseUp"/>
<Ellipse Name="c2" Tag="2" Style="{StaticResource PointEllipseStyle}"
MouseDown="PointMouseDown" MouseMove="PointMouseMove" MouseUp="PointMouseUp"/>
<Ellipse Name="c3" Tag="3" Style="{StaticResource PointEllipseStyle}"
MouseDown="PointMouseDown" MouseMove="PointMouseMove" MouseUp="PointMouseUp"/>
<Ellipse Name="c4" Tag="4" Style="{StaticResource PointEllipseStyle}"
MouseDown="PointMouseDown" MouseMove="PointMouseMove" MouseUp="PointMouseUp"/>
</Grid>
</Grid>
</Page>
关键部分在workspace对应的Grid控件中
第二步,PageLight.xaml.cs中添加以下代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace wpfbase
{
public partial class PageLight : Page
{
// 定义像素分辨率比,屏幕尺寸
private double widthRatio, heightRatio;
private double[] screenSize;
// 定义十字交叉线
private LineGeometry lineX, lineY;
private GeometryGroup linegroup;
private bool CROSSLINESHOW;
private bool SelectRect;
private List<double[]> rect_rois;
private List<bool> rect_Flags;
public PageLight()
{
InitializeComponent();
CROSSLINESHOW = false;
SelectRect = false;
// 初始化十字交叉线
lineX = new LineGeometry();
lineY = new LineGeometry();
linegroup = new GeometryGroup();
rect_rois = new List<double[]>();
rect_Flags = new List<bool>();
crossline.Data = linegroup;
linegroup.Children.Add(lineX);
linegroup.Children.Add(lineY);
// 工作区添加缩放事件响应
this.SizeChanged += new System.Windows.SizeChangedEventHandler(PageLightResized);
// 工作区添加滚轮事件冒泡
workspace.PreviewMouseWheel += (sender, e) => {
var eventArg = new MouseWheelEventArgs(e.MouseDevice,e.Timestamp,e.Delta);
eventArg.RoutedEvent = UIElement.MouseWheelEvent;
eventArg.Source = sender;
workspace.RaiseEvent(eventArg);
};
}
/* ------------- 导航栏按钮点击响应 --------------*/
// 矩形标注按钮
private void LabelRectangle(object sender, RoutedEventArgs e) {
SelectRect = !SelectRect;
if(SelectRect) {
CROSSLINESHOW = true;
button_rectangle.Foreground = new SolidColorBrush(Colors.LightYellow );
image.Cursor = Cursors.Cross;
crossline.Cursor = Cursors.Cross;
}
else {
CROSSLINESHOW = false;
button_rectangle.Foreground = new SolidColorBrush(Colors.Black );
image.Cursor = Cursors.Arrow;
crossline.Cursor = Cursors.Arrow;
}
}
// 取消选中按钮
private const int ROIStart = 7; // 定义ROI开始索引
private void SelectCancel(object sender, RoutedEventArgs e) {
labelbox.SelectedIndex = -1;
if(labelbox.Tag != null) {
int index = (int)labelbox.Tag;
Rectangle rectangle = workspace.Children[index+ROIStart] as Rectangle;
rectangle.Fill = null;
rectangle.Tag = 0;
labelbox.Tag = null;
PointClose();
}
}
/* ------------labelbox框事件响应-------------- */
// 键盘响应
private void LabelboxKeyResponse(object sender, KeyEventArgs e) {
if(e.Key == Key.Delete) {
LabelboxItemDelete();
PointClose();
}
}
// 响应Delete按键
private void LabelboxItemDelete() {
int index = labelbox.SelectedIndex;
if(index != -1) {
workspace.Children.RemoveAt(index+ROIStart);
rect_rois.RemoveAt(index);
rect_Flags.RemoveAt(index);
labelbox.Items.RemoveAt(index);
labelbox.SelectedIndex = -1;
labelbox.Tag = null;
}
}
// 选中标注响应事件
private void SelectChange(object sender, SelectionChangedEventArgs e) {
int index = labelbox.SelectedIndex;
if(index == -1) return;
FlashPoint();
PointShow();
Rectangle rectangle = workspace.Children[index+ROIStart] as Rectangle;
rectangle.Fill = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#5588ffcc"));
rectangle.Tag = 1;
if(labelbox.Tag != null) {
int lastindex = (int)labelbox.Tag;
Rectangle lastrectangle = workspace.Children[lastindex+ROIStart] as Rectangle;
lastrectangle.Fill = null;
lastrectangle.Tag = 0;
}
labelbox.Tag = index;
}
/* ------------工作区事件响应-------------- */
// 工作区尺寸变化事件响应
private void PageLightResized(object sender, System.EventArgs e) {
// 窗口及图像的ActualWidth均发生改变
// 窗口实际尺寸,图像比例下实际尺寸
var group_image = workspace.FindResource("Imageview") as TransformGroup;
var scale_image = group_image.Children[0] as ScaleTransform;
var move_image = group_image.Children[1] as TranslateTransform;
move_image.X = 0;
move_image.Y = 0;
scale_image.ScaleX = 1;
scale_image.ScaleY = 1;
DoRoisWheelZoom();
DoRoisResize();
FlashPoint();
}
// img为可视区域,image为图像
private bool lMouseDown;
private bool rMouseDown;
private Point position;
private Point imageposition;
// 鼠标左键按下响应
private void ImgMouseLeftButtonDown(object sender, MouseButtonEventArgs e) {
if(!SelectRect) {
return;}
if(!image.IsMouseOver && !crossline.IsMouseOver)