├── App.config
├── App.xaml
├── App.xaml.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── Matting.csproj
├── Matting.sln
├── MattingAlg.cs
├── Model
├── MODNET.zip.001
├── MODNET.zip.002
└── MODNET.zip.003
├── Properties
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Resources.resx
├── Settings.Designer.cs
└── Settings.settings
├── README.md
├── README_EN.md
└── bin
├── Debug
└── ScreenCapturer.dll
└── Release
└── ScreenCapturer.dll
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace Matting
10 | {
11 | ///
12 | /// App.xaml 的交互逻辑
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
25 |
26 |
33 |
34 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 | using System.Threading;
5 | using System.Windows;
6 | using System.Windows.Forms;
7 | using System.Windows.Media;
8 | using System.Windows.Media.Imaging;
9 | using System.Windows.Threading;
10 |
11 | namespace Matting
12 | {
13 | ///
14 | /// MainWindow.xaml 的交互逻辑
15 | ///
16 | public partial class MainWindow : Window
17 | {
18 | System.Drawing.Color mBgColor = System.Drawing.Color.Transparent;//背景颜色
19 | string mBgfile = string.Empty;//背景文件
20 | OpenCvSharp.Size mOrgSize;//原始图像大小
21 | MattingAlg mMattingAlg;//抠图AI算法
22 |
23 | OpenCvSharp.Mat mBackground;//背景
24 | OpenCvSharp.Mat mForeGround;//前景
25 | Dispatcher UI;
26 | public MainWindow()
27 | {
28 | InitializeComponent();
29 | this.mMattingAlg = new MattingAlg();
30 | this.UI = Dispatcher.CurrentDispatcher;
31 | }
32 | ///
33 | /// 选择文件
34 | ///
35 | private void File_Click(object sender, RoutedEventArgs e)
36 | {
37 | System.Windows.Controls.MenuItem menu = sender as System.Windows.Controls.MenuItem;
38 |
39 | //加载本地图像
40 | if (menu.Header.ToString() == "图像文件")
41 | {
42 | this.imageST.Visibility = Visibility.Visible;
43 | this.videoST.Visibility = Visibility.Hidden;
44 | Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
45 | ofd.Filter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png";
46 | if (ofd.ShowDialog() != true) return;
47 |
48 | BitmapImage bitmap = new BitmapImage(new Uri(ofd.FileName));
49 | this.ShowOrgImage(bitmap);
50 | Thread thread = new Thread(() =>
51 | {
52 | OpenCvSharp.Mat image = OpenCvSharp.Cv2.ImRead(ofd.FileName, OpenCvSharp.ImreadModes.Color);
53 | if (this.mForeGround != null) this.mForeGround.Dispose();
54 | this.mForeGround = this.Matting(image);
55 | this.ShowMatting(this.mForeGround);//显示抠图
56 |
57 | this.ShowBG();//显示背景
58 | });
59 | thread.Start();
60 |
61 | }
62 | //截图
63 | else if (menu.Header.ToString() == "截图")
64 | {
65 | this.imageST.Visibility = Visibility.Visible;
66 | this.videoST.Visibility = Visibility.Hidden;
67 | this.Hide();
68 | System.Threading.Thread.Sleep(200);
69 |
70 | ScreenCapturer.ScreenCapturerTool screenCapturer = new ScreenCapturer.ScreenCapturerTool();
71 | if (screenCapturer.ShowDialog() == System.Windows.Forms.DialogResult.OK)
72 | {
73 | this.ShowOrgImage(this.ConvertToBitmapSource(screenCapturer.Image));//显示图像
74 | //this.Matting(screenCapturer.Image);//抠图
75 | OpenCvSharp.Mat image = this.Convert2Mat(screenCapturer.Image);
76 | Thread thread = new Thread(() =>
77 | {
78 | if (this.mForeGround != null) this.mForeGround.Dispose();
79 | this.mForeGround = this.Matting(image);
80 | this.ShowMatting(this.mForeGround);//显示抠图
81 | this.ShowBG();//显示背景
82 | });
83 | thread.Start();
84 | }
85 | this.Show();
86 | }
87 | //剪切板
88 | else if (menu.Header.ToString() == "剪切板")
89 | {
90 | this.imageST.Visibility = Visibility.Visible;
91 | this.videoST.Visibility = Visibility.Hidden;
92 | System.Drawing.Bitmap bitmap = this.GetClipboardImage();
93 | this.ShowOrgImage(this.ConvertToBitmapSource(bitmap));//显示图像
94 | //this.Matting(bitmap);//抠图
95 | OpenCvSharp.Mat image = this.Convert2Mat(bitmap);
96 | Thread thread = new Thread(() =>
97 | {
98 | if (this.mForeGround != null) this.mForeGround.Dispose();
99 | this.mForeGround = this.Matting(image);
100 | this.ShowMatting(this.mForeGround);//显示抠图
101 | this.ShowBG();//显示背景
102 | });
103 | thread.Start();
104 | }
105 | //视频
106 | else if (menu.Header.ToString() == "视频")
107 | {
108 | this.imageST.Visibility = Visibility.Hidden;
109 | this.videoST.Visibility = Visibility.Visible;
110 |
111 | Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
112 | ofd.Filter = "*.*|*.mp4;*.avi";
113 | if (ofd.ShowDialog() != true) return;
114 | // 加载视频文件
115 | this.ShowOrgVideo(ofd.FileName);
116 | Thread thread = new Thread(() =>
117 | {
118 | // 创建VideoCapture对象,打开视频文件
119 | using (OpenCvSharp.VideoCapture capture = new OpenCvSharp.VideoCapture(ofd.FileName))
120 | {
121 | this.Matting(capture);
122 | }
123 | });
124 | thread.Start();
125 |
126 | }
127 | }
128 | ///
129 | /// 获取剪切板截图
130 | ///
131 | ///
132 | private System.Drawing.Bitmap GetClipboardImage()
133 | {
134 | System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Windows.Forms.Clipboard.GetImage();
135 | if (bmp == null)
136 | {
137 | string[] bmpFilters = new string[] { ".bmp", ".jpg", ".jpeg", ".tiff", ".tif", ".png" };
138 | var files = System.Windows.Forms.Clipboard.GetFileDropList();
139 |
140 | string[] Filtersarr = new string[files.Count];
141 | files.CopyTo(Filtersarr, 0);
142 | Filtersarr = Filtersarr.Where(x => bmpFilters.Contains(System.IO.Path.GetExtension(x).ToLower())).ToArray();
143 | if (Filtersarr.Length > 0)
144 | {
145 | var imagebyte = File.ReadAllBytes(Filtersarr[0]);
146 | bmp = new System.Drawing.Bitmap(new MemoryStream(imagebyte));
147 | }
148 | }
149 | return bmp;
150 | }
151 | ///
152 | /// Image转BitMapImage
153 | ///
154 | private BitmapSource ConvertToBitmapSource(System.Drawing.Image image)
155 | {
156 | using (System.IO.MemoryStream stream = new MemoryStream())
157 | {
158 | // 将图像保存到内存流中
159 | image.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
160 |
161 | // 创建BitmapSource
162 | BitmapImage bitmapImage = new BitmapImage();
163 | bitmapImage.BeginInit();
164 | bitmapImage.StreamSource = new MemoryStream(stream.ToArray());
165 | bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
166 | bitmapImage.EndInit();
167 |
168 | return bitmapImage;
169 | }
170 | }
171 | ///
172 | /// 选择背景
173 | ///
174 | private void BackGround_Click(object sender, RoutedEventArgs e)
175 | {
176 | System.Windows.Controls.MenuItem menu = sender as System.Windows.Controls.MenuItem;
177 | //纯色背景
178 | if (menu.Header.ToString() == "背景颜色")
179 | {
180 | ColorDialog colorDialog = new ColorDialog();
181 | System.Drawing.Color bgcolor = this.mBgColor;
182 | colorDialog.Color = bgcolor;
183 | if (colorDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
184 | if (this.mBackground != null) this.mBackground.Dispose();
185 | this.mBgColor = colorDialog.Color;
186 | this.mBgfile = string.Empty;
187 |
188 | this.ShowBG();//显示背景
189 | }
190 | //背景图像
191 | else if (menu.Header.ToString() == "背景图像")
192 | {
193 | Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
194 | ofd.Filter = "*.*|*.bmp;*.jpg;*.jpeg;*.tiff;*.tiff;*.png"; ;
195 | if (ofd.ShowDialog() != true) return;
196 | if (this.mBackground != null) this.mBackground.Dispose();
197 |
198 | this.mBgfile = ofd.FileName;
199 | this.mBgColor = System.Drawing.Color.Transparent;
200 |
201 | this.ShowBG();//显示背景
202 | }
203 |
204 | }
205 | ///
206 | /// 显示背景
207 | ///
208 | void ShowBG()
209 | {
210 | if (this.mBgColor != System.Drawing.Color.Transparent)
211 | {
212 | this.mBackground = this.GenerateBgMat(this.mBgColor);//生成背景Mat
213 | this.ShowBackground(this.mBackground);//显示背景
214 | }
215 | else if (this.mBgfile != string.Empty)
216 | {
217 | this.mBackground = this.GenerateBgMat(this.mBgfile);//生成背景Mat
218 | this.ShowBackground(this.mBackground);//显示背景
219 | }
220 | }
221 | ///
222 | /// 保存
223 | ///
224 | private void Save_Click(object sender, RoutedEventArgs e)
225 | {
226 | System.Windows.Controls.MenuItem menu = sender as System.Windows.Controls.MenuItem;
227 | String exePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
228 | if (menu.Header.ToString() == "保存整体")//背景+前景
229 | {
230 | // 创建融合图像的目标Mat对象
231 | OpenCvSharp.Mat blendedImage = new OpenCvSharp.Mat(this.mForeGround.Size(), OpenCvSharp.MatType.CV_8UC4);
232 | for (int i = 0; i < mForeGround.Cols; i++)
233 | {
234 | for (int j = 0; j < mForeGround.Rows; j++)
235 | {
236 | int index = j * mForeGround.Cols + i;
237 | if (mForeGround.At(j, i)[3] > 128)
238 | {
239 | blendedImage.At(j, i)[0] = mForeGround.At(j, i)[0];
240 | blendedImage.At(j, i)[1] = mForeGround.At(j, i)[1];
241 | blendedImage.At(j, i)[2] = mForeGround.At(j, i)[2];
242 | blendedImage.At(j, i)[3] = mForeGround.At(j, i)[3];
243 | }
244 | else
245 | {
246 | blendedImage.At(j, i)[0] = this.mBackground.At(j, i)[0];
247 | blendedImage.At(j, i)[1] = mBackground.At(j, i)[1];
248 | blendedImage.At(j, i)[2] = mBackground.At(j, i)[2];
249 | blendedImage.At(j, i)[3] = 255;
250 | }
251 | }
252 | }
253 | // 选择保存参数
254 | OpenCvSharp.ImageEncodingParam[] parameters = new OpenCvSharp.ImageEncodingParam[]
255 | {
256 | new OpenCvSharp.ImageEncodingParam(OpenCvSharp.ImwriteFlags.PngCompression, 9) // 设置PNG压缩级别
257 | };
258 | // 保存融合后的图像
259 | OpenCvSharp.Cv2.ImWrite(exePath + "\\full.png", blendedImage, parameters);
260 | }
261 | else if (menu.Header.ToString() == "保存前景")//前景only
262 | {
263 | // 选择保存参数
264 | OpenCvSharp.ImageEncodingParam[] parameters = new OpenCvSharp.ImageEncodingParam[]
265 | {
266 | new OpenCvSharp.ImageEncodingParam(OpenCvSharp.ImwriteFlags.PngCompression, 9) // 设置PNG压缩级别
267 | };
268 | // 保存融合后的图像
269 | OpenCvSharp.Cv2.ImWrite(exePath + "\\foreground.png", this.mForeGround, parameters);
270 | }
271 |
272 | }
273 |
274 | ///
275 | /// 生成纯色背景图
276 | ///
277 | OpenCvSharp.Mat GenerateBgMat(System.Drawing.Color bgcolor)
278 | {
279 | OpenCvSharp.Mat bgMat = new OpenCvSharp.Mat(this.mOrgSize, OpenCvSharp.MatType.CV_8UC3);
280 | for (int i = 0; i < bgMat.Cols; i++)
281 | {
282 | for (int j = 0; j < bgMat.Rows; j++)
283 | {
284 | int index = j * bgMat.Cols + i;
285 | bgMat.At(j, i)[0] = bgcolor.B;
286 | bgMat.At(j, i)[1] = bgcolor.G;
287 | bgMat.At(j, i)[2] = bgcolor.R;
288 | }
289 | }
290 |
291 | return bgMat;
292 | }
293 | ///
294 | /// 生成背景图像
295 | ///
296 | OpenCvSharp.Mat GenerateBgMat(string file)
297 | {
298 | OpenCvSharp.Mat image = OpenCvSharp.Cv2.ImRead(file, OpenCvSharp.ImreadModes.Color);
299 | OpenCvSharp.Size newSize = this.mOrgSize;
300 |
301 | int targetWidth = newSize.Width; // 目标宽度
302 | int targetHeight = newSize.Height; // 目标高度
303 |
304 | // 计算缩放因子
305 | double scaleX = (double)targetWidth / image.Width;
306 | double scaleY = (double)targetHeight / image.Height;
307 | double scale = Math.Min(scaleX, scaleY);
308 |
309 | // 缩放图像
310 | OpenCvSharp.Mat scaledImage = new OpenCvSharp.Mat();
311 | OpenCvSharp.Cv2.Resize(image, scaledImage, new OpenCvSharp.Size(), scale, scale);
312 |
313 | // 计算填充大小
314 | int paddingWidth = targetWidth - scaledImage.Width;
315 | int paddingHeight = targetHeight - scaledImage.Height;
316 |
317 | // 计算边界偏移量
318 | int top = paddingHeight / 2;
319 | int bottom = paddingHeight - top;
320 | int left = paddingWidth / 2;
321 | int right = paddingWidth - left;
322 |
323 | // 进行填充
324 | OpenCvSharp.Mat paddedImage = new OpenCvSharp.Mat();
325 | OpenCvSharp.Cv2.CopyMakeBorder(scaledImage, paddedImage, top, bottom, left, right, OpenCvSharp.BorderTypes.Constant, new OpenCvSharp.Scalar(255, 255, 255));
326 |
327 | return paddedImage;
328 | }
329 | ///
330 | /// 显示原始视频
331 | ///
332 | ///
333 | void ShowOrgVideo(string videopath)
334 | {
335 | // 加载视频文件
336 | this.mOrgVideo.Source = new Uri(videopath);
337 | this.mOrgVideo.Play();
338 | }
339 | ///
340 | /// 显示原始图像
341 | ///
342 | void ShowOrgImage(BitmapSource img)
343 | {
344 | this.mImage.Source = img;//显示图像
345 | }
346 | ///
347 | /// 对视频抠图
348 | ///
349 | void Matting(OpenCvSharp.VideoCapture video)
350 | {
351 | // 检查视频是否成功打开
352 | if (!video.IsOpened())
353 | {
354 | Console.WriteLine("无法打开视频文件.");
355 | return;
356 | }
357 |
358 | string exePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
359 | // 设置视频文件保存路径和参数
360 | string videoFilePath = exePath + "\\path_to_save_video.mp4"; // 替换为你希望保存的视频文件路径
361 | OpenCvSharp.FourCC fourCC = OpenCvSharp.FourCC.MP4V; // 视频编码器的FourCC码
362 | int fps = 2; // 视频的帧率
363 | // 创建VideoWriter对象
364 | using (OpenCvSharp.VideoWriter writer = new OpenCvSharp.VideoWriter(videoFilePath, fourCC, fps, new OpenCvSharp.Size(video.FrameWidth, video.FrameHeight)))
365 | {
366 | // 循环读取视频帧
367 | while (true)
368 | {
369 | // 读取下一帧
370 | OpenCvSharp.Mat frame = new OpenCvSharp.Mat();
371 | if (!video.Read(frame))
372 | break;
373 | video.PosFrames += (int)video.Fps / fps;
374 | OpenCvSharp.Mat matting = this.MattingVideo(frame);
375 |
376 | // 写入当前帧到视频文件
377 | writer.Write(matting);
378 |
379 | // 释放当前帧的资源
380 | matting.Dispose();
381 |
382 | // 释放当前帧的资源
383 | frame.Dispose();
384 |
385 | }
386 | }
387 | UI.Invoke(new Action(delegate
388 | {
389 | System.Windows.MessageBox.Show("Matting Video finished!");
390 | this.mMattingVideo.Source = new Uri(videoFilePath);
391 | this.mMattingVideo.Play();
392 |
393 | }));
394 |
395 | }
396 | ///
397 | ///将System.Drawing.Image转换为OpenCV Mat
398 | ///
399 | OpenCvSharp.Mat Convert2Mat(System.Drawing.Image img)
400 | {
401 | // 将图像转换为Bitmap
402 | System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(img);
403 | // 获取图像的宽度和高度
404 | int width = bitmap.Width;
405 | int height = bitmap.Height;
406 |
407 | OpenCvSharp.Mat image = new OpenCvSharp.Mat(new OpenCvSharp.Size(width, height), OpenCvSharp.MatType.CV_8UC3);
408 | // 遍历图像的像素
409 | for (int y = 0; y < height; y++)
410 | {
411 | for (int x = 0; x < width; x++)
412 | {
413 | // 获取像素的颜色
414 | System.Drawing.Color color = bitmap.GetPixel(x, y);
415 | image.At(y, x)[0] = color.B;
416 | image.At(y, x)[1] = color.G;
417 | image.At(y, x)[2] = color.R;
418 | }
419 | }
420 | // 释放资源
421 | bitmap.Dispose();
422 |
423 | return image;
424 | }
425 | ///
426 | /// 抠图
427 | ///
428 | void Matting(System.Drawing.Image img)
429 | { // 将图像转换为Bitmap
430 | System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(img);
431 | // 获取图像的宽度和高度
432 | int width = bitmap.Width;
433 | int height = bitmap.Height;
434 |
435 | OpenCvSharp.Mat image = new OpenCvSharp.Mat(new OpenCvSharp.Size(width, height), OpenCvSharp.MatType.CV_8UC3);
436 | // 遍历图像的像素
437 | for (int y = 0; y < height; y++)
438 | {
439 | for (int x = 0; x < width; x++)
440 | {
441 | // 获取像素的颜色
442 | System.Drawing.Color color = bitmap.GetPixel(x, y);
443 | image.At(y, x)[0] = color.B;
444 | image.At(y, x)[1] = color.G;
445 | image.At(y, x)[2] = color.R;
446 | }
447 | }
448 | // 释放资源
449 | bitmap.Dispose();
450 |
451 | Thread thread = new Thread(() =>
452 | {
453 | if (this.mForeGround != null) this.mForeGround.Dispose();
454 | this.mForeGround = this.Matting(image);
455 | this.ShowMatting(this.mForeGround);//显示抠图
456 | });
457 | thread.Start();
458 | }
459 |
460 | ///
461 | /// 抠图
462 | ///
463 | OpenCvSharp.Mat Matting(OpenCvSharp.Mat image)
464 | {
465 |
466 | this.mOrgSize = image.Size();
467 | // Define the new size for the resized image
468 | int min = Math.Min(image.Rows, image.Cols);
469 | float scale = 512.0f / min;
470 | int w = (int)(image.Cols * scale);
471 | int h = (int)(image.Rows * scale);
472 | int rw = w - w % 32;
473 | int rh = h - h % 32;
474 | OpenCvSharp.Size mnewSize = new OpenCvSharp.Size(rw, rh);
475 |
476 | // Create a new Mat object to store the resized image
477 | OpenCvSharp.Mat resizedImage = new OpenCvSharp.Mat();
478 |
479 | // Resize the image
480 | OpenCvSharp.Cv2.Resize(image, resizedImage, mnewSize, 0, 0, OpenCvSharp.InterpolationFlags.Linear);
481 | OpenCvSharp.Mat alpha = this.mMattingAlg.Seg(resizedImage);
482 |
483 | OpenCvSharp.Mat alpharesize = new OpenCvSharp.Mat();
484 | OpenCvSharp.Cv2.Resize(alpha, alpharesize, new OpenCvSharp.Size(image.Cols, image.Rows), 0, 0, OpenCvSharp.InterpolationFlags.Linear);
485 |
486 | alpha.Dispose();
487 |
488 | return this.GenerateForeGround(image, alpharesize);
489 | }
490 | ///
491 | /// 抠图
492 | ///
493 | OpenCvSharp.Mat MattingVideo(OpenCvSharp.Mat image)
494 | {
495 |
496 | this.mOrgSize = image.Size();
497 | // Define the new size for the resized image
498 | int min = Math.Min(image.Rows, image.Cols);
499 | float scale = 512.0f / min;
500 | int w = (int)(image.Cols * scale);
501 | int h = (int)(image.Rows * scale);
502 | int rw = w - w % 32;
503 | int rh = h - h % 32;
504 | OpenCvSharp.Size mnewSize = new OpenCvSharp.Size(rw, rh);
505 |
506 | // Create a new Mat object to store the resized image
507 | OpenCvSharp.Mat resizedImage = new OpenCvSharp.Mat();
508 |
509 | // Resize the image
510 | OpenCvSharp.Cv2.Resize(image, resizedImage, mnewSize, 0, 0, OpenCvSharp.InterpolationFlags.Linear);
511 | OpenCvSharp.Mat alpha = this.mMattingAlg.Seg(resizedImage);
512 |
513 | OpenCvSharp.Mat alpharesize = new OpenCvSharp.Mat();
514 | OpenCvSharp.Cv2.Resize(alpha, alpharesize, new OpenCvSharp.Size(image.Cols, image.Rows), 0, 0, OpenCvSharp.InterpolationFlags.Linear);
515 |
516 | alpha.Dispose();
517 |
518 | OpenCvSharp.Mat forground = new OpenCvSharp.Mat(image.Size(), OpenCvSharp.MatType.CV_8UC3);
519 | for (int y = 0; y < image.Rows; y++)
520 | {
521 | for (int x = 0; x < image.Cols; x++)
522 | {
523 | float al = (byte)(255 * alpharesize.At(y, x));
524 | int ind = y * image.Cols + x;
525 | if (al > 128)
526 | {
527 | forground.At(y, x)[0] = image.At(y, x)[0]; // Blue
528 | forground.At(y, x)[1] = image.At(y, x)[1]; // Green
529 | forground.At(y, x)[2] = image.At(y, x)[2]; // Red
530 | }
531 | else
532 | {
533 | forground.At(y, x)[0] = 0; // Blue
534 | forground.At(y, x)[1] = 0; // Green
535 | forground.At(y, x)[2] = 0; // Red
536 | }
537 |
538 | }
539 | }
540 |
541 | return forground;
542 |
543 | }
544 | ///
545 | /// 生成前景图像
546 | ///
547 | /// 原始图像
548 | /// Alpha
549 | ///
550 | OpenCvSharp.Mat GenerateForeGround(OpenCvSharp.Mat orgImg, OpenCvSharp.Mat Alpha)
551 | {
552 |
553 | OpenCvSharp.Mat forground = new OpenCvSharp.Mat(orgImg.Size(), OpenCvSharp.MatType.CV_8UC4);
554 | for (int y = 0; y < orgImg.Rows; y++)
555 | {
556 | for (int x = 0; x < orgImg.Cols; x++)
557 | {
558 | forground.At(y, x)[0] = orgImg.At(y, x)[0]; // Blue
559 | forground.At(y, x)[1] = orgImg.At(y, x)[1]; // Green
560 | forground.At(y, x)[2] = orgImg.At(y, x)[2]; // Red
561 | forground.At(y, x)[3] = (byte)(255 * Alpha.At(y, x)); // Alpha
562 | }
563 | }
564 | orgImg.Dispose();
565 | Alpha.Dispose();
566 |
567 | return forground;
568 | }
569 | ///
570 | /// 显示背景
571 | ///
572 | void ShowBackground(OpenCvSharp.Mat bg)
573 | {
574 | UI.Invoke(new Action(delegate
575 | {
576 | WriteableBitmap bp = new WriteableBitmap(bg.Cols, bg.Rows, 96, 96, PixelFormats.Bgra32, null);
577 | // 设置像素数据,将所有像素的透明度设置为半透明
578 | byte[] pixelData = new byte[bg.Cols * bg.Rows * 4];
579 | Array.Clear(pixelData, 0, pixelData.Length);
580 | for (int y = 0; y < bg.Rows; y++)
581 | {
582 | for (int x = 0; x < bg.Cols; x++)
583 | {
584 | int ind = y * bg.Cols + x;
585 | pixelData[4 * ind] = bg.At(y, x)[0]; // Blue
586 | pixelData[4 * ind + 1] = bg.At(y, x)[1]; // Green
587 | pixelData[4 * ind + 2] = bg.At(y, x)[2]; // Red
588 | pixelData[4 * ind + 3] = 255; // Alpha
589 |
590 | }
591 | }
592 |
593 | bp.WritePixels(new Int32Rect(0, 0, bg.Cols, bg.Rows), pixelData, bg.Cols * 4, 0);
594 | // 创建一个BitmapImage对象,将WriteableBitmap作为源
595 | this.mBg.Source = bp;
596 |
597 | }));
598 | }
599 | ///
600 | /// 显示前景
601 | ///
602 | void ShowMatting(OpenCvSharp.Mat forground)
603 | {
604 | UI.Invoke(new Action(delegate
605 | {
606 | WriteableBitmap bp = new WriteableBitmap(forground.Cols, forground.Rows, 96, 96, PixelFormats.Bgra32, null);
607 | // 设置像素数据,将所有像素的透明度设置为半透明
608 | byte[] pixelData = new byte[forground.Cols * forground.Rows * 4];
609 | Array.Clear(pixelData, 0, pixelData.Length);
610 | for (int y = 0; y < forground.Rows; y++)
611 | {
612 | for (int x = 0; x < forground.Cols; x++)
613 | {
614 | int ind = y * forground.Cols + x;
615 | pixelData[4 * ind] = forground.At(y, x)[0]; // Blue
616 | pixelData[4 * ind + 1] = forground.At(y, x)[1]; // Green
617 | pixelData[4 * ind + 2] = forground.At(y, x)[2]; // Red
618 | pixelData[4 * ind + 3] = forground.At(y, x)[3]; // Alpha
619 | }
620 | }
621 |
622 | bp.WritePixels(new Int32Rect(0, 0, forground.Cols, forground.Rows), pixelData, forground.Cols * 4, 0);
623 | // 创建一个BitmapImage对象,将WriteableBitmap作为源
624 | this.mMatting.Source = bp;
625 |
626 | }));
627 |
628 | }
629 | }
630 | }
631 |
--------------------------------------------------------------------------------
/Matting.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {83E3A5B3-B42F-4C02-B307-D06F1BAA3D7C}
8 | WinExe
9 | Matting
10 | Matting
11 | v4.7.2
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | 4.0
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | MSBuild:Compile
56 | Designer
57 |
58 |
59 | MSBuild:Compile
60 | Designer
61 |
62 |
63 | App.xaml
64 | Code
65 |
66 |
67 | MainWindow.xaml
68 | Code
69 |
70 |
71 |
72 |
73 | Code
74 |
75 |
76 | True
77 | True
78 | Resources.resx
79 |
80 |
81 | True
82 | Settings.settings
83 | True
84 |
85 |
86 | ResXFileCodeGenerator
87 | Resources.Designer.cs
88 |
89 |
90 | SettingsSingleFileGenerator
91 | Settings.Designer.cs
92 |
93 |
94 |
95 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/Matting.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.32602.291
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Matting", "Matting.csproj", "{83E3A5B3-B42F-4C02-B307-D06F1BAA3D7C}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {83E3A5B3-B42F-4C02-B307-D06F1BAA3D7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {83E3A5B3-B42F-4C02-B307-D06F1BAA3D7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {83E3A5B3-B42F-4C02-B307-D06F1BAA3D7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {83E3A5B3-B42F-4C02-B307-D06F1BAA3D7C}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {BD782FF1-FB57-4D0B-B87A-9B255B9DA8D6}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/MattingAlg.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.ML.OnnxRuntime;
2 | using Microsoft.ML.OnnxRuntime.Tensors;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using System.Windows;
11 |
12 | namespace Matting
13 | {
14 | ///
15 | /// 人像抠图算法
16 | ///
17 | class MattingAlg
18 | {
19 | InferenceSession mSession;
20 | public bool mReady = false;
21 | public MattingAlg()
22 | {
23 | Thread thread = new Thread(() =>
24 | {
25 | this.LoadONNXModel();
26 | this.mReady = true;
27 | });
28 | thread.Start();
29 |
30 | }
31 |
32 | void LoadONNXModel()
33 | {
34 | if (this.mSession != null)
35 | this.mSession.Dispose();
36 |
37 | string exePath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
38 | string model_path = exePath + @"\MODNET.onnx";
39 | if (!File.Exists(model_path))
40 | {
41 | MessageBox.Show(model_path + " not exist!");
42 | return;
43 | }
44 |
45 | this.mSession = new InferenceSession(model_path);
46 | }
47 | ///
48 | /// 分割人像
49 | ///
50 | /// 输入RGB图像
51 | /// alpha
52 | public OpenCvSharp.Mat Seg(OpenCvSharp.Mat image)
53 | {
54 |
55 | OpenCvSharp.Mat floatImage = new OpenCvSharp.Mat();
56 | image.ConvertTo(floatImage, OpenCvSharp.MatType.CV_32FC3);
57 | // 将像素值归一化到0到255的范围内
58 | float[] transformedImg = new float[3 * image.Cols * image.Rows];
59 | for (int i = 0; i < image.Cols; i++)
60 | {
61 | for (int j = 0; j < image.Rows; j++)
62 | {
63 | int index = j * image.Cols + i;
64 | transformedImg[index] = (floatImage.At(j, i)[2] / 255.0f - 0.5f) / 0.5f;
65 | transformedImg[image.Cols * image.Rows + index] = (floatImage.At(j, i)[1] / 255.0f - 0.5f) / 0.5f;
66 | transformedImg[2 * image.Cols * image.Rows + index] = (floatImage.At(j, i)[0] / 255.0f - 0.5f) / 0.5f;
67 | }
68 | }
69 |
70 | var tensor = new DenseTensor(transformedImg, new[] { 1, 3, image.Rows, image.Cols });
71 | var inputs = new List
72 | {
73 | NamedOnnxValue.CreateFromTensor("img", tensor)
74 | };
75 |
76 | var results = this.mSession.Run(inputs);
77 | var alphaArray = results.First().AsTensor().ToArray();
78 | OpenCvSharp.Mat alpha = new OpenCvSharp.Mat(new OpenCvSharp.Size(image.Cols, image.Rows), OpenCvSharp.MatType.CV_32FC1);
79 | for (int i = 0; i < image.Cols; i++)
80 | {
81 | for (int j = 0; j < image.Rows; j++)
82 | {
83 | int index = j * image.Cols + i;
84 | float a = alphaArray[index];
85 | alpha.At(j, i) = a;
86 | }
87 | }
88 | return alpha;
89 |
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/Model/MODNET.zip.001:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIDajiangtang/MODNET-Matting-tool/1fdb0f18b46c57e5c90a73ea8c8094bce5fcfdc4/Model/MODNET.zip.001
--------------------------------------------------------------------------------
/Model/MODNET.zip.002:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIDajiangtang/MODNET-Matting-tool/1fdb0f18b46c57e5c90a73ea8c8094bce5fcfdc4/Model/MODNET.zip.002
--------------------------------------------------------------------------------
/Model/MODNET.zip.003:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIDajiangtang/MODNET-Matting-tool/1fdb0f18b46c57e5c90a73ea8c8094bce5fcfdc4/Model/MODNET.zip.003
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("Matting")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("Matting")]
15 | [assembly: AssemblyCopyright("Copyright © 2023")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // 将 ComVisible 设置为 false 会使此程序集中的类型
20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请设置
25 | //.csproj 文件中的 CultureYouAreCodingWith
26 | //例如,如果您在源文件中使用的是美国英语,
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(未在页面中找到资源时使用,
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(未在页面中找到资源时使用,
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
52 | //通过使用 "*",如下所示:
53 | // [assembly: AssemblyVersion("1.0.*")]
54 | [assembly: AssemblyVersion("1.0.0.0")]
55 | [assembly: AssemblyFileVersion("1.0.0.0")]
56 |
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 |
12 | namespace Matting.Properties
13 | {
14 | ///
15 | /// 强类型资源类,用于查找本地化字符串等。
16 | ///
17 | // 此类是由 StronglyTypedResourceBuilder
18 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
19 | // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
20 | // (以 /str 作为命令选项),或重新生成 VS 项目。
21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
24 | internal class Resources
25 | {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources()
33 | {
34 | }
35 |
36 | ///
37 | /// 返回此类使用的缓存 ResourceManager 实例。
38 | ///
39 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
40 | internal static global::System.Resources.ResourceManager ResourceManager
41 | {
42 | get
43 | {
44 | if ((resourceMan == null))
45 | {
46 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Matting.Properties.Resources", typeof(Resources).Assembly);
47 | resourceMan = temp;
48 | }
49 | return resourceMan;
50 | }
51 | }
52 |
53 | ///
54 | /// 重写当前线程的 CurrentUICulture 属性,对
55 | /// 使用此强类型资源类的所有资源查找执行重写。
56 | ///
57 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
58 | internal static global::System.Globalization.CultureInfo Culture
59 | {
60 | get
61 | {
62 | return resourceCulture;
63 | }
64 | set
65 | {
66 | resourceCulture = value;
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 |
12 | namespace Matting.Properties
13 | {
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
17 | {
18 |
19 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
20 |
21 | public static Settings Default
22 | {
23 | get
24 | {
25 | return defaultInstance;
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 简体中文 | [English](README_EN.md)
2 |
3 | # MODNET-Matting-tool
4 | 基于深度学习的抠图工具C#推理工具
5 | [[`Paper`](https://arxiv.org/pdf/2011.11961.pdf )]
6 |
7 |
8 | 关注微信公众号:**人工智能大讲堂**
9 |
10 | 后台回复【mat】获取安装包以及模型文件
11 |
12 | ## 支持多种文件类型
13 | 文件->图像文件 加载本地图像文件
14 | 文件->截图
15 | 文件->剪切板
16 | 文件->视频 为了效率目前Fps为2,即每秒两帧
17 |
18 |
19 |
20 | ## 支持背景替换
21 | 背景->背景颜色 背景替换为纯色
22 |
23 | 背景->背景图像 将背景替换为图像
24 |
25 |
26 | ## 支持多种保存选择
27 | 保存->保存整体 前景+背景
28 |
29 |
30 | 保存->保存前景 只保存前景
31 |
32 | 保存的图像和视频都在exe所在路径下。
33 |
34 |
35 |
36 | ## 源码编译
37 | 1.下载源码到本地
38 | 2.Visual Studio打开.sln项目解决方案
39 | 3.安装Nuget包
40 | 3.1在Visual Studio中,鼠标右键单击项目并选择“管理NuGet程序包”。
41 | 3.2在“NuGet包管理器”窗口中,选择“浏览”选项卡。
42 | 3.3搜索Microsoft.ML.OnnxRuntime,选择1.15.1版本,点击安装
43 | 3.4搜索OpenCvSharp4,选择4.8.0版本,点击安装
44 | 3.5搜索OpenCvSharp4.runtime.win,选择4.8.0版本,点击安装
45 | 3.6找到Debug或者Release下的ScreenCapture.dll,添加到引用中
46 | 4.将MODNET.onnx放到exe路径下
47 | 5.运行程序
48 |
49 | 注意:有时前景图像中可能带有一些碎片,可以使用OpenCV最大连通域算法去掉小的碎片。
50 |
--------------------------------------------------------------------------------
/README_EN.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](README.md)
2 |
3 | # MODNET-Matting-tool
4 | C# reasoning tool based on deep learning matting tool
5 | [[`Paper`](https://arxiv.org/pdf/2011.11961.pdf )]
6 |
7 |
8 | wechat:**人工智能大讲堂**
9 |
10 | Reply [mat] in the background to get the installation package and model files
11 |
12 |
13 | ## Supports multiple input file types
14 | File -> Image File Load a local image file
15 | File -> Screenshot
16 | File -> Clipboard
17 | File -> Video For efficiency, the current Fps is 2, that is, two frames per second
18 |
19 |
20 |
21 |
22 | ## Support background replacement
23 | Background->Background Colo: Replace the background with a solid color
24 |
25 | Background -> Background Image: Replace the background with an image
26 |
27 |
28 | ## Supports multiple save options
29 | Save -> Save Overall :Foreground+Background
30 |
31 |
32 | Save -> Save Foreground: Save only foreground
33 |
34 | The saved images and videos are all under the path of the exe.
35 |
36 |
37 |
38 |
39 | ## source code compilation
40 | 1. Download the source code to the local
41 | 2.Visual Studio opens the .sln project solution
42 | 3. Install the Nuget package
43 | 3.1 In Visual Studio, right-click on the project and select "Manage NuGet Packages".
44 | 3.2 In the "NuGet Package Manager" window, select the "Browse" tab.
45 | 3.3 Search for Microsoft.ML.OnnxRuntime, select version 1.15.1, and click Install
46 | 3.4 Search for OpenCvSharp4, select version 4.8.0, and click Install
47 | 3.5 Search for OpenCvSharp4.runtime.win, select version 4.8.0, and click Install
48 | 3.6 Find ScreenCapture.dll under Debug or Release and add it to the reference
49 | 5. Put MODNET.onnx in the exe path
50 | 6. Run the program
51 |
--------------------------------------------------------------------------------
/bin/Debug/ScreenCapturer.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIDajiangtang/MODNET-Matting-tool/1fdb0f18b46c57e5c90a73ea8c8094bce5fcfdc4/bin/Debug/ScreenCapturer.dll
--------------------------------------------------------------------------------
/bin/Release/ScreenCapturer.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AIDajiangtang/MODNET-Matting-tool/1fdb0f18b46c57e5c90a73ea8c8094bce5fcfdc4/bin/Release/ScreenCapturer.dll
--------------------------------------------------------------------------------