最近在开发一个视觉工具项目。突发奇想,想写一个隐藏式的导航栏,对处理过的图片做一个记录,并保存在导航栏中,点击对应的位置,可以唤出对应的图片。
界面展示
设计器界面
实际界面
代码
View.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2.5*"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Name="ImageG" Grid.Column="0" Grid.Row="0">
<Border Name="BtnBo" HorizontalAlignment="Left" Width="15" Height="100" BorderThickness="0" Background="#7FBEF0F6" MouseEnter="HideMenu_MouseEnter">
<Image Source="../Resource/Image/menu0.png" Height="50"></Image>
</Border>
<Border Name="HideMenu" Background="#7FBEF0F6" MouseLeave="HideMenu_MouseLeave" Width="100" HorizontalAlignment="Left" Margin="-100 0 0 0">
<ListBox Background="{x:Null}" ItemsSource="{Binding ImageList}" SelectedItem="{Binding ImageSelected}" BorderThickness="0" SelectedIndex="{Binding ImageIndex}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Width="35"></Image>
<Label Content="{Binding Tag}" FontSize="10" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Image Source="{Binding ImageSource}" Margin="5"></Image>
<Border Background="#66EDF1CC" Width="80" HorizontalAlignment="Right">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="图像信息" VerticalAlignment="Top" HorizontalAlignment="Center"></Label>
<TextBlock Grid.Row="1" Text="{Binding SrcImage.Rows}" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
<TextBlock Grid.Row="2" Text="{Binding SrcImage.Cols}" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
</Grid>
</Border>
</Grid>
<GroupBox Header="Log" Grid.Column="0" Grid.Row="1" Margin="5">
<ScrollViewer>
<TextBlock Name="LogContent" Text="{Binding LogContent}" ScrollViewer.CanContentScroll="True"></TextBlock>
</ScrollViewer>
</GroupBox>
<Grid Grid.Row="0" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Column="0" Grid.Row="0" Margin="5" Content="清空图像" Command="{Binding ClearImageCommand}"></Button>
<Button Grid.Column="1" Grid.Row="0" Margin="5" Content="加载图像" Command="{Binding LoadImageCommand}"></Button>
<Button Grid.Column="0" Grid.Row="1" Margin="5" Content="平移" Command="{Binding TranslationCommand}"></Button>
<Button Grid.Column="0" Grid.Row="2" Margin="5" Content="旋转" Command="{Binding RotateCommand}"></Button>
<Button Grid.Column="0" Grid.Row="3" Margin="5" Content="放大" Command="{Binding BiggerCommand}"></Button>
<Button Grid.Column="0" Grid.Row="4" Margin="5" Content="缩小" Command="{Binding SmallerCommand}"></Button>
<Grid Grid.Column="1" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="垂直"></Label>
<TextBox Grid.Column="1" Grid.Row="0" Margin="1" Text="{Binding Vertical}" InputScope="Number"></TextBox>
<Label Grid.Column="0" Grid.Row="1" Content="水平"></Label>
<TextBox Grid.Column="1" Grid.Row="1" Margin="1" Text="{Binding Horizontal}" InputScope="Number"></TextBox>
</Grid>
<Grid Grid.Column="1" Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="角度" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
<TextBox Grid.Column="1" Grid.Row="0" Margin="1 15 1 15" Text="{Binding Angle}" InputScope="Number"></TextBox>
</Grid>
<Grid Grid.Column="1" Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="倍数" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
<TextBox Grid.Column="1" Grid.Row="0" Margin="1 15 1 15" Text="{Binding BigTimes}" InputScope="Number"></TextBox>
</Grid>
<Grid Grid.Column="1" Grid.Row="4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="倍数" HorizontalAlignment="Center" VerticalAlignment="Center"></Label>
<TextBox Grid.Column="1" Grid.Row="0" Margin="1 15 1 15" Text="{Binding SmalleTimes}" InputScope="Number"></TextBox>
</Grid>
</Grid>
</Grid>
View.cs
public partial class AffineView : Window
{
private Storyboard mStoryboard0;
private Storyboard mStoryboard1;
private AffineViewModel viewmodel;
private bool isShowedMenu = false;
public AffineView()
{
InitializeComponent();
viewmodel = new AffineViewModel();
this.DataContext = viewmodel;
InitAnimation();
}
private void InitAnimation()
{
//! 展示
DoubleAnimation da = new DoubleAnimation();
da.From = null;
da.To = 100;
da.Duration = new Duration(TimeSpan.FromSeconds(0.5));
HideMenu.RenderTransform = new TranslateTransform();
mStoryboard0 = new Storyboard();
mStoryboard0.Children.Add(da);
Storyboard.SetTarget(da, HideMenu);
Storyboard.SetTargetProperty(da, new PropertyPath("RenderTransform.X"));
//!隐藏
DoubleAnimation doa = new DoubleAnimation();
doa.From = null;
doa.To = 0;
doa.Duration = new Duration(TimeSpan.FromSeconds(0.5));
mStoryboard1 = new Storyboard();
mStoryboard1.Children.Add(doa);
Storyboard.SetTarget(doa, HideMenu);
Storyboard.SetTargetProperty(doa, new PropertyPath("RenderTransform.X"));
}
private void HideMenu_MouseEnter(object sender, MouseEventArgs e)
{
if (!isShowedMenu)
{
mStoryboard0.Begin(this);
isShowedMenu = true;
BtnBo.Visibility = Visibility.Collapsed;
}
}
private void HideMenu_MouseLeave(object sender, MouseEventArgs e)
{
if (isShowedMenu)
{
mStoryboard1.Begin(this);
isShowedMenu = false;
BtnBo.Visibility = Visibility.Visible;
}
}
ViewModel.cs
public class AffineViewModel : ObservableObject
{
private ObservableCollection<ImageModel> _imageModels;
public ObservableCollection<ImageModel> ImageList
{
get => _imageModels;
set
{
if (value.Count > 10)
{
value.RemoveAt(0);
}
SetProperty(ref _imageModels, value);
}
}
private ImageModel _imageSelected;
public ImageModel ImageSelected
{
get => _imageSelected;
set
{
if (_imageSelected != value)
{
if (value != null)
{
UpdateImage(value.Image);
}
}
SetProperty(ref _imageSelected, value);
}
}
private BitmapSource _imageSource;
public BitmapSource ImageSource
{
get => _imageSource;
set
{
SetProperty(ref _imageSource, value);
}
}
private string _logContent;
public string LogContent
{
get => _logContent;
set
{
SetProperty(ref _logContent, value);
}
}
private Mat _srcImage;
public Mat SrcImage
{
get => _srcImage;
set
{
SetProperty(ref _srcImage, value);
}
}
private int _imageIndex;
public int ImageIndex
{
get => _imageIndex;
set
{
SetProperty(ref _imageIndex, value);
}
}
private int _vertical;
public int Vertical
{
get => _vertical;
set
{
SetProperty(ref _vertical, value);
}
}
private int _horizontal;
public int Horizontal
{
get => _horizontal;
set
{
SetProperty(ref _horizontal, value);
}
}
private int _angle;
public int Angle
{
get => _angle;
set
{
SetProperty(ref _angle, value);
}
}
private int _bigTimes;
public int BigTimes
{
get => _bigTimes;
set
{
SetProperty(ref _bigTimes, value);
}
}
private int _smalleTimes;
public int SmalleTimes
{
get => _smalleTimes;
set
{
SetProperty(ref _smalleTimes, value);
}
}
public IRelayCommand ClearImageCommand { get; set; }
public IRelayCommand LoadImageCommand { get; set; }
public IRelayCommand TranslationCommand { get; set; }
public IRelayCommand RotateCommand { get; set; }
public IRelayCommand BiggerCommand { get; set; }
public IRelayCommand SmallerCommand { get; set; }
public AffineViewModel()
{
ClearImageCommand = new RelayCommand(ClearImage);
LoadImageCommand = new RelayCommand(LoadImage);
TranslationCommand = new RelayCommand(Translation);
RotateCommand = new RelayCommand(Rotate);
BiggerCommand = new RelayCommand(Bigger);
SmallerCommand = new RelayCommand(Smaller);
ImageList = new ObservableCollection<ImageModel>();
Reecord("仿射变换");
}
private void Smaller()
{
if (SrcImage != null)
{
if (SmalleTimes != 0)
{
OpenCvSharp.Point center = new OpenCvSharp.Point(SrcImage.Cols / 2, SrcImage.Rows / 2);
float angle = 0;
float scale = 1.0f / SmalleTimes;
Mat rot_mat = Cv2.GetRotationMatrix2D(center, angle, scale);
Mat warp_rotate_dst = Mat.Zeros(SrcImage.Rows, SrcImage.Cols, SrcImage.Type());
Cv2.WarpAffine(SrcImage, warp_rotate_dst, rot_mat, warp_rotate_dst.Size());
var hBitmap = warp_rotate_dst.ToBitmap().GetHbitmap();
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
ImageModel model = new ImageModel()
{
Image = bitmapSource,
Tag = "仿射变换_缩小"
};
ImageList.Add(model);
ImageSource = bitmapSource;
ImageIndex = ImageList.Count - 1;
GDIHelper.DeleteObject(hBitmap);
SrcImage = warp_rotate_dst;
Reecord("仿射变换_缩小");
}
}
}
private void Bigger()
{
if (SrcImage != null)
{
if (BigTimes != 0)
{
OpenCvSharp.Point center = new OpenCvSharp.Point(SrcImage.Cols / 2, SrcImage.Rows / 2);
float angle = 0;
float scale = BigTimes;
Mat rot_mat = Cv2.GetRotationMatrix2D(center, angle, scale);
Mat warp_rotate_dst = Mat.Zeros(SrcImage.Rows, SrcImage.Cols, SrcImage.Type());
double new_height = SrcImage.Rows * scale;
double new_width = SrcImage.Cols * scale;
rot_mat.At<double>(0, 2) += (new_width - SrcImage.Cols) / 2;
rot_mat.At<double>(1, 2) += (new_height - SrcImage.Rows) / 2;
OpenCvSharp.Rect bbox = new RotatedRect(new Point2f(SrcImage.Cols / 2 * scale, SrcImage.Rows / 2 * scale), new Size2f(SrcImage.Cols * scale, SrcImage.Rows * scale), angle).BoundingRect();
Cv2.WarpAffine(SrcImage, warp_rotate_dst, rot_mat, bbox.Size);
var hBitmap = warp_rotate_dst.ToBitmap().GetHbitmap();
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
ImageModel model = new ImageModel()
{
Image = bitmapSource,
Tag = "仿射变换_放大"
};
ImageList.Add(model);
ImageSource = bitmapSource;
ImageIndex = ImageList.Count - 1;
GDIHelper.DeleteObject(hBitmap);
SrcImage = warp_rotate_dst;
Reecord("仿射变换_放大");
}
}
}
private void Rotate()
{
if (SrcImage != null)
{
OpenCvSharp.Point center = new OpenCvSharp.Point(SrcImage.Cols / 2, SrcImage.Rows / 2);
float angle = 0.0f - Angle;
float scale = 1.0f;
Mat rot_mat = Cv2.GetRotationMatrix2D(center, angle, scale);
Mat warp_rotate_dst = Mat.Zeros(SrcImage.Rows, SrcImage.Cols, SrcImage.Type());
//Cv2.WarpAffine(SrcImage, warp_rotate_dst, rot_mat, warp_rotate_dst.Size());
double sin_angle = Math.Sin(Math.Abs(angle) * Math.PI / 180);
double cos_angle = Math.Cos(Math.Abs(angle) * Math.PI / 180);
double new_height = SrcImage.Cols * sin_angle + SrcImage.Rows * cos_angle;
double new_width = SrcImage.Cols * cos_angle + SrcImage.Rows * sin_angle;
rot_mat.At<double>(0, 2) += (new_width - SrcImage.Cols) / 2;
rot_mat.At<double>(1, 2) += (new_height - SrcImage.Rows) / 2;
OpenCvSharp.Rect bbox = new RotatedRect(new Point2f(SrcImage.Cols / 2, SrcImage.Rows / 2), new Size2f(SrcImage.Cols, SrcImage.Rows), angle).BoundingRect();
Cv2.WarpAffine(SrcImage, warp_rotate_dst, rot_mat, bbox.Size);
var hBitmap = warp_rotate_dst.ToBitmap().GetHbitmap();
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
ImageModel model = new ImageModel()
{
Image = bitmapSource,
Tag = "仿射变换_旋转"
};
ImageList.Add(model);
ImageSource = bitmapSource;
ImageIndex = ImageList.Count - 1;
GDIHelper.DeleteObject(hBitmap);
SrcImage = warp_rotate_dst;
Reecord("仿射变换_旋转");
}
}
private void Translation()
{
if (SrcImage != null)
{
Point2f[] srcTri = new Point2f[3];
srcTri[0] = new Point2f(0.0f, 0.0f);
srcTri[1] = new Point2f(SrcImage.Cols - 1.0f, 0.0f);
srcTri[2] = new Point2f(0.0f, SrcImage.Rows - 1.0f);
Point2f[] dstTri = new Point2f[3];
dstTri[0] = new Point2f(Horizontal, Vertical);
dstTri[1] = new Point2f(SrcImage.Cols - 1.0f + Horizontal, Vertical);
dstTri[2] = new Point2f(Horizontal, SrcImage.Rows - 1.0f + Vertical);
Mat warp_mat = Cv2.GetAffineTransform(srcTri, dstTri);
Mat warp_dst = Mat.Zeros(SrcImage.Rows + Vertical, SrcImage.Cols + Horizontal, SrcImage.Type());
Cv2.WarpAffine(SrcImage, warp_dst, warp_mat, warp_dst.Size());
var hBitmap = warp_dst.ToBitmap().GetHbitmap();
var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(
hBitmap, IntPtr.Zero, Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
ImageModel model = new ImageModel()
{
Image = bitmapSource,
Tag = "仿射变换_平移"
};
ImageList.Add(model);
ImageSource = bitmapSource;
ImageIndex = ImageList.Count - 1;
GDIHelper.DeleteObject(hBitmap);
SrcImage = warp_dst;
Reecord("仿射变换_平移");
}
}
private void LoadImage()
{
OpenFileDialog file = new OpenFileDialog();
file.ShowDialog();
if (file.FileName != null && file.FileName != "")
{
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.UriSource = new Uri(file.FileName, UriKind.Absolute);
bi.EndInit();
ImageModel model = new ImageModel()
{
Image = bi,
Tag = "原始图像"
};
ImageList.Add(model);
Reecord("加载图像");
//SrcImage = new Mat(file.FileName, ImreadModes.AnyColor);
}
}
private void ClearImage()
{
if (ImageList != null || ImageList.Count > 0)
{
ImageList.Clear();
ImageSource = null;
}
}
private void UpdateImage(BitmapSource source)
{
ImageSource = source;
Bitmap bitmap;
using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
{
BitmapEncoder encoder = new BmpBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(source));
encoder.Save(ms);
bitmap = new Bitmap(ms);
}
SrcImage = BitmapConverter.ToMat(bitmap);
}
private void Reecord(string content)
{
string log = DateTime.Now.ToString("hh:mm:ff") + "\t" + content + "\n";
LogContent += log;
}
}
写在结尾
这篇文章,作为实战分享文章,希望能够帮助到正在写WPF的朋友么,如果有什么问题也可以留言或者私信我