一、效果
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7aab1192775488fc39ff7780cbb80edc.png)
二、函数说明
2.1 细节增强
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c983a506cfab45d40d526105f7beeab1.png)
2.2 铅笔
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/565051ffc415251c40e8f327107b2f07.png)
2.3 磨皮
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/faadb5e7335b5581ebf73c623cb6f5b7.png)
2.4 卡通
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/70ad1dc8f9701964f57327345a9d86f3.png)
三、代码
3.1 MainViewModel
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
namespace Demo
{
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private WriteableBitmap _previewImage1;
public WriteableBitmap PreviewImage1
{
get { return _previewImage1; }
set { _previewImage1 = value; PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("")); }
}
private WriteableBitmap _previewImage2;
public WriteableBitmap PreviewImage2
{
get { return _previewImage2; }
set { _previewImage2 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private WriteableBitmap _previewImage3;
public WriteableBitmap PreviewImage3
{
get { return _previewImage3; }
set { _previewImage3 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private WriteableBitmap _previewImage4;
public WriteableBitmap PreviewImage4
{
get { return _previewImage4; }
set { _previewImage4 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private WriteableBitmap _previewImage5;
public WriteableBitmap PreviewImage5
{
get { return _previewImage5; }
set { _previewImage5 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private WriteableBitmap _previewImage6;
public WriteableBitmap PreviewImage6
{
get { return _previewImage6; }
set { _previewImage6 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private BitmapImage Bitmap2BitmapImage(Bitmap bitmap ) {
using (MemoryStream ms = new MemoryStream()) {
bitmap.Save(ms,ImageFormat.Bmp);
BitmapImage bi = new BitmapImage();
bi.BeginInit();
bi.StreamSource = ms;
bi.CacheOption = BitmapCacheOption.OnLoad;
bi.EndInit();
bi.Freeze();
return bi;
}
}
private Bitmap Text(Bitmap img,string str) {
Bitmap bmp = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(img, 0, 0, bmp.Width, bmp.Height);
g.DrawString(str, new Font("Verdana", 50), new SolidBrush(Color.Black), new PointF(100, 0));
}
return bmp;
}
private Bitmap Text2(Bitmap img, string str)
{
Bitmap bmp = new Bitmap(img.Width, img.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
using (Graphics g = Graphics.FromImage(bmp))
{
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.DrawImage(img, 0, 0, bmp.Width, bmp.Height);
g.DrawString(str, new Font("Verdana", 50), new SolidBrush(Color.White), new PointF(100, 0));
}
return bmp;
}
private string _path = "bird1.png";
public string Path
{
get { return _path; }
set { _path = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
public Mat ImageProcess1()
{
var image1 = new Image<Bgr, byte>(Path);
var image0 = image1.Mat.Clone();
Application.Current.Dispatcher.Invoke(() =>
{
PreviewImage1 = new WriteableBitmap(Bitmap2BitmapImage(Text(image1.Bitmap, "原图")));
});
return image0;
}
private float _param1 = 10;
public float Param1
{
get { return _param1; }
set { _param1 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private float _param2 = 0.15f;
public float Param2
{
get { return _param2; }
set { _param2 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
public void ImageProcess2(Mat image)
{
Mat image2 = new Mat();
CvInvoke.DetailEnhance(image, image2,Param1,Param2);
Application.Current.Dispatcher.Invoke(() =>
{
PreviewImage2 = new WriteableBitmap(Bitmap2BitmapImage(Text(image2.Bitmap, "细节增强")));
});
}
private float _param3 = 60;
public float Param3
{
get { return _param3; }
set { _param3 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private float _param4 = 0.07f;
public float Param4
{
get { return _param4; }
set { _param4 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private float _param5 = 0.02f;
public float Param5
{
get { return _param5; }
set { _param5 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
public void ImageProcess3(Mat image)
{
Mat image3 = new Mat();
Mat image4 = new Mat();
CvInvoke.PencilSketch(image, image3, image4, Param3,Param4,Param5);
Application.Current.Dispatcher.Invoke(() =>
{
PreviewImage3 = new WriteableBitmap(Bitmap2BitmapImage(Text(image3.Bitmap, "黑白铅笔")));
PreviewImage4 = new WriteableBitmap(Bitmap2BitmapImage(Text(image4.Bitmap, "彩色铅笔")));
});
}
private float _param6 = 60;
public float Param6
{
get { return _param6; }
set { _param6 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private float _param7 = 0.4f;
public float Param7
{
get { return _param7; }
set { _param7 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
public void ImageProcess4(Mat image)
{
Mat image5 = new Mat();
CvInvoke.EdgePreservingFilter(image, image5,EdgePreservingFilterFlag.RecursFilter, Param6, Param7);
Application.Current.Dispatcher.Invoke(() =>
{
PreviewImage5 = new WriteableBitmap(Bitmap2BitmapImage(Text2(image5.Bitmap, "美颜磨皮")));
});
}
private float _param8 = 60;
public float Param8
{
get { return _param8; }
set { _param8 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
private float _param9 = 0.45f;
public float Param9
{
get { return _param9; }
set { _param9 = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("")); }
}
public void ImageProcess5(Mat image)
{
Mat image6 = new Mat();
CvInvoke.Stylization(image, image6,Param8,Param9);
Application.Current.Dispatcher.Invoke(() =>
{
PreviewImage6 = new WriteableBitmap(Bitmap2BitmapImage(Text2(image6.Bitmap, "卡通漫画")));
});
}
public MainViewModel() {
var mat = ImageProcess1();
ImageProcess2(mat);
ImageProcess3(mat);
ImageProcess4(mat);
ImageProcess5(mat);
}
private CommandBase _selectCommand;
public CommandBase SelectCommand
{
get
{
if (_selectCommand == null)
{
_selectCommand = new CommandBase()
{
DoCanExecute = new Func<object, bool>((o) => true),
DoExecute = new Action<object>((o) =>
{
System.Windows.Forms.OpenFileDialog openFileDialog = new System.Windows.Forms.OpenFileDialog();
openFileDialog.Title = "请选择图片";
var res = openFileDialog.ShowDialog();
if (res == System.Windows.Forms.DialogResult.OK) {
Path = openFileDialog.FileName;
Task.Factory.StartNew(() =>
{
var mat= ImageProcess1();
ImageProcess2(mat);
ImageProcess3(mat);
ImageProcess4(mat);
ImageProcess5(mat);
});
}
})
};
}
return _selectCommand;
}
set { _selectCommand = value; }
}
}
}
3.2 MainWindow.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 Demo
{
public partial class MainWindow : Window
{
MainViewModel MainViewModel = new MainViewModel();
public MainWindow()
{
InitializeComponent();
this.DataContext = MainViewModel;
}
private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Task.Factory.StartNew(() =>
{
MainViewModel.ImageProcess2(MainViewModel.ImageProcess1());
});
}
private void Slider_ValueChanged_1(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Task.Factory.StartNew(() =>
{
MainViewModel.ImageProcess3(MainViewModel.ImageProcess1());
});
}
private void Slider_ValueChanged_2(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Task.Factory.StartNew(() =>
{
MainViewModel.ImageProcess4(MainViewModel.ImageProcess1());
});
}
private void Slider_ValueChanged_3(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Task.Factory.StartNew(() =>
{
MainViewModel.ImageProcess5(MainViewModel.ImageProcess1());
});
}
}
}
3.3 MainWindow.xaml
<Window x:Class="Demo.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:Demo"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="1600">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<!--图片显示-->
<Grid>
<Image Source="{Binding PreviewImage1}"/>
<StackPanel VerticalAlignment="Bottom">
<Button Command="{Binding SelectCommand}" Height="60" Width="100" Content="图片选择" FontSize="20" Background="Transparent"/>
</StackPanel>
</Grid>
<Grid Grid.Column="1">
<Image Source="{Binding PreviewImage2}"/>
<StackPanel VerticalAlignment="Bottom">
<Slider Value="{Binding Param1}" Maximum="200" TickFrequency="10" LargeChange="10" ValueChanged="Slider_ValueChanged"/>
<Slider Value="{Binding Param2}" Maximum="1" TickFrequency="0.05" LargeChange="0.05" ValueChanged="Slider_ValueChanged"/>
</StackPanel>
</Grid>
<Grid Grid.Column="2">
<Image Source="{Binding PreviewImage3}"/>
<StackPanel VerticalAlignment="Bottom">
<Slider Value="{Binding Param3}" Maximum="200" TickFrequency="10" LargeChange="10" ValueChanged="Slider_ValueChanged_1"/>
<Slider Value="{Binding Param4}" Maximum="1" TickFrequency="0.05" LargeChange="0.05" ValueChanged="Slider_ValueChanged_1"/>
<Slider Value="{Binding Param5}" Maximum="0.1" TickFrequency="0.01" LargeChange="0.01" ValueChanged="Slider_ValueChanged_1"/>
</StackPanel>
</Grid>
<Grid Grid.Row="1" >
<Image Source="{Binding PreviewImage4}"/>
</Grid>
<Grid Grid.Row="1" Grid.Column="1">
<Image Source="{Binding PreviewImage5}"/>
<StackPanel VerticalAlignment="Bottom">
<Slider Value="{Binding Param6}" Maximum="200" TickFrequency="10" LargeChange="10" ValueChanged="Slider_ValueChanged_2"/>
<Slider Value="{Binding Param7}" Maximum="1" TickFrequency="0.05" LargeChange="0.05" ValueChanged="Slider_ValueChanged_2"/>
</StackPanel>
</Grid>
<Grid Grid.Row="1" Grid.Column="2">
<Image Source="{Binding PreviewImage6}"/>
<StackPanel VerticalAlignment="Bottom">
<Slider Value="{Binding Param8}" Maximum="200" TickFrequency="10" LargeChange="10" ValueChanged="Slider_ValueChanged_3"/>
<Slider Value="{Binding Param9}" Maximum="1" TickFrequency="0.05" LargeChange="0.05" ValueChanged="Slider_ValueChanged_3"/>
</StackPanel>
</Grid>
</Grid>
</Window>