using Microsoft.Win32; 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; using System.Windows.Forms; using MouseEventArgs = System.Windows.Input.MouseEventArgs; using OpenFileDialog = System.Windows.Forms.OpenFileDialog; using System.Threading; using DataFormats = System.Windows.DataFormats; using System.IO; using OpenCvSharp; using System.Runtime.InteropServices; using Point = System.Windows.Point; namespace 拼图排序 { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : System.Windows.Window { Point previousPoint; bool isTranslateStart = false; ImageMerge imageMerge = new ImageMerge(); ushort[] gray; ushort[] mat_gray; ushort slider_value = 0; Image[] Images = new Image[100]; OpenCvSharp.Mat OriginalMat = new OpenCvSharp.Mat(); int UpDateTime = 1000; public BitmapSource MatToBitmapSource(Mat mat, ref ushort[] gray) { PixelFormat pf = PixelFormats.Gray16; int rawStride = (mat.Width * pf.BitsPerPixel + 7) / 8; mat.GetArray(out gray); return BitmapSource.Create(mat.Width, mat.Height, 96, 96, pf, null, gray, rawStride); } private void OpenImages(string[] files) { OriginalMat = Cv2.ImRead(files[0], ImreadModes.Unchanged); mat_gray = new ushort[OriginalMat.Height * OriginalMat.Width]; OriginalMat.GetArray(out mat_gray); imageMerge.ImageHeight = OriginalMat.Height / 4; imageMerge.ImageWidth = OriginalMat.Width / 4; gray = new ushort[imageMerge.ImageHeight * imageMerge.ImageWidth]; for (int i = 0; i < 16; i++) { BitmapImage bmp = new BitmapImage(); Image img = new Image(); img.Source = bmp; img.Stretch = Stretch.Uniform; img.Width = imageMerge.ImageWidth; img.Height = imageMerge.ImageHeight; img.SetValue(RenderOptions.BitmapScalingModeProperty, BitmapScalingMode.NearestNeighbor);//取消抗锯齿 inside.Children.Add(img); Images[imageMerge.ImageTotalPages] = img; imageMerge.ImageRow = imageMerge.ImageTotalPages / imageMerge.ImageColumnPages;//该照片所在行 imageMerge.ImageColumn = imageMerge.ImageTotalPages % imageMerge.ImageColumnPages;//该照片所在列 Canvas.SetTop(img, 0 + imageMerge.ImageRow * (imageMerge.ImageHeight + imageMerge.ImageMargin.Bottom)); Canvas.SetLeft(img, 0 + imageMerge.ImageColumn * (imageMerge.ImageWidth + imageMerge.ImageMargin.Right)); imageMerge.ImageTotalPages++; } } private void TaskImage(int i) { while (true) { Thread.Sleep(UpDateTime); if (imageMerge.ImageTotalPages > 0) { OpenCvSharp.Rect rect = new OpenCvSharp.Rect(imageMerge.ImageWidth * (i % 4), imageMerge.ImageHeight * (i / 4), imageMerge.ImageWidth, imageMerge.ImageHeight);//设置范围 Mat cropped_image = new Mat(OriginalMat, rect);//裁剪图像 cropped_image = cropped_image * slider_value; this.Dispatcher.Invoke(new Action(() => { Images[i].Source = MatToBitmapSource(cropped_image, ref gray); })); } } } public MainWindow() { InitializeComponent(); imageMerge.ImageMargin.Left = 0; imageMerge.ImageMargin.Right = 0; imageMerge.ImageMargin.Top = 0; imageMerge.ImageMargin.Bottom = 0; imageMerge.ImageTotalPages = 0; imageMerge.ImageRowPages = 4;//行图片张数 imageMerge.ImageColumnPages = 4;//列图片张数 List<int> list = new List<int>(); int taskCount = 16; for (int i = 0; i < taskCount; i++) { list.Add(i); } var tasks = list.Select(i => { return Task.Run(() => TaskImage(i)); }); Task.WhenAll(tasks); } private void outsidewrapper_PreviewMouseDown(object sender, MouseButtonEventArgs e) { if (e.MiddleButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released) { previousPoint = e.GetPosition(outside); isTranslateStart = true; } e.Handled = true; } private void outsidewrapper_PreviewMouseMove(object sender, MouseEventArgs e) { if (e.MiddleButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released) { if (isTranslateStart) { Point currentPoint = e.GetPosition(outside); //不能用 inside,必须用outside System.Windows.Vector v = currentPoint - previousPoint; TransformGroup tg = inside.RenderTransform as TransformGroup; tg.Children.Add(new TranslateTransform(v.X, v.Y)); //centerX和centerY用外部包装元素的坐标,不能用内部被变换的Canvas元素的坐标 previousPoint = currentPoint; } } else { //适用于静止图像 Point point2 = Mouse.GetPosition(inside);//获取Canvas坐标 UInt32 x, y; x = (UInt32)point2.X; y = (UInt32)point2.Y; //xyGray.Text = $"x:{x} y:{y}";//显示坐标值 if (x >= 0 && x < OriginalMat.Width && y >= 0 && y < OriginalMat.Height) xyGray.Text = $"x:{x} y:{y} gray:{mat_gray[y * OriginalMat.Width + x]}"; else xyGray.Text = $"x:{x} y:{y} gray:- "; } e.Handled = true; } private void outside_PreviewMouseUp(object sender, MouseButtonEventArgs e) { if (e.MiddleButton == MouseButtonState.Pressed && e.LeftButton == MouseButtonState.Released && e.RightButton == MouseButtonState.Released) { if (isTranslateStart) { isTranslateStart = false; } } e.Handled = true; } private void outside_PreviewMouseWheel(object sender, MouseWheelEventArgs e) { Point currentPoint = e.GetPosition(outside); //不能用 inside,必须用outside TransformGroup tg = inside.RenderTransform as TransformGroup; double s = ((double)e.Delta) / 1000.0 + 1.0; if (OriginalMat.Height * tg.Value.M22 < 200 || OriginalMat.Width * tg.Value.M11 < 200) { if (s > 1.0)//当图像像素宽度和高度小于200的时候只能放大,不再缩小 tg.Children.Add(new ScaleTransform(s, s, currentPoint.X, currentPoint.Y)); } else tg.Children.Add(new ScaleTransform(s, s, currentPoint.X, currentPoint.Y)); e.Handled = true; } private void BtnClickLoadPic(object sender, RoutedEventArgs e) { OpenFileDialog openFileDialog1 = new OpenFileDialog(); //openFileDialog1.InitialDirectory = "E:\\"; //打开默认路径 openFileDialog1.Filter = "All Files|*.*|PNG Files|*.png|JPG Files|*.jpg|TIF Files|*.tif"; openFileDialog1.FilterIndex = 1; openFileDialog1.RestoreDirectory = true; openFileDialog1.Multiselect = true; if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK) { try { OpenImages(openFileDialog1.FileNames); } catch (Exception ex) { System.Windows.MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); } } } private void BtnClickFullScreen(object sender, RoutedEventArgs e) { TransformGroup tg = inside.RenderTransform as TransformGroup; System.Windows.Media.Matrix value = new System.Windows.Media.Matrix(); value.M11 = outside.ActualWidth / OriginalMat.Width / tg.Value.M11;//缩放倍数为Border的尺寸 value.M22 = outside.ActualHeight / OriginalMat.Height / tg.Value.M22; value.OffsetX = (0 - tg.Value.OffsetX) * value.M11;//调整偏移XY到(0,0) value.OffsetY = (0 - tg.Value.OffsetY) * value.M22; MatrixTransform matrixTransform = new MatrixTransform(value);//添加矩阵变换 tg.Children.Add(matrixTransform); e.Handled = true; } private void BtnClickClearScreen(object sender, RoutedEventArgs e) { imageMerge.ImageTotalPages = 0; inside.Children.Clear(); inside.Children.RemoveRange(0, inside.Children.Count); } private void ImagePanel_Drop(object sender, System.Windows.DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) { // Note that you can have more than one file. string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); OpenImages(files); } } private void SliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e) { slider_value = (ushort)SliderGray.Value; } } //图像合并 public class ImageMerge { public int ImageWidth; public int ImageHeight; public UInt32 ImageTotalPages;//图像总共张数 public UInt32 ImageSelectPage;//选中的图片 public UInt32 ImageRowPages;//一行存放照片的张数 public UInt32 ImageColumnPages;//一列存放照片的张数 public Margin ImageMargin;//相邻照片之间的边距 public UInt32 ImageRow;//照片所在行 public UInt32 ImageColumn;//照片所在列 public bool IsBusy; } public struct Margin { public UInt32 Left; public UInt32 Right; public UInt32 Top; public UInt32 Bottom; } }MainWindow.xaml.cs
<Window x:Class="拼图排序.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:拼图排序" mc:Ignorable="d" Title="MainWindow" Height="800" Width="1000"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="40"/> <RowDefinition Height="40"/> </Grid.RowDefinitions> <Border x:Name="outside" Background="Gray" PreviewMouseDown="outsidewrapper_PreviewMouseDown" PreviewMouseMove="outsidewrapper_PreviewMouseMove" PreviewMouseUp="outside_PreviewMouseUp" PreviewMouseWheel="outside_PreviewMouseWheel" Drop="ImagePanel_Drop" AllowDrop="true" ClipToBounds="True" ScrollViewer.HorizontalScrollBarVisibility="Visible" > <Canvas x:Name="inside" Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType={x:Type Border}}}" Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType={x:Type Border}}}" ScrollViewer.HorizontalScrollBarVisibility="Visible"> <Canvas.RenderTransform> <TransformGroup/> </Canvas.RenderTransform> </Canvas> </Border> <Slider x:Name="SliderGray" Minimum ="1" Maximum="100" SmallChange="1" LargeChange="1" Grid.Row="1" VerticalAlignment="Center" Margin="40,0,60,0" ValueChanged="SliderValueChanged" ></Slider> <TextBlock Text="{Binding ElementName=SliderGray,Path=Value, StringFormat=0}" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,10,0" ></TextBlock> <TextBlock x:Name="xyGray" Grid.Row="2" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20,0,0,0" ></TextBlock> <Button Click="BtnClickLoadPic" Grid.Row="2" HorizontalAlignment="Right" Content="加载图片" /> <Button Click="BtnClickFullScreen" Grid.Row="2" HorizontalAlignment="Right" Content=" 全屏 " Margin="0,0,60,0" /> <Button Click="BtnClickClearScreen" Grid.Row="2" HorizontalAlignment="Right" Content=" 清屏 " Margin="0,0,120,0" /> </Grid> </Window>MainWindow.xaml
本程序使用了OpenCvSharp第三方库
标签:Task,Windows,System,new,图像,using,WPF,public,imageMerge From: https://www.cnblogs.com/lizhiqiang0204/p/17129658.html