内容简介

将Alpha Matting抠图算法由c++ 版本移植至c#环境。 主要采用OpenCV的C#版本Emgu取代c++支撑的OpenCV。

参考资料

  1. http://www.inf.ufrgs.br/~eslgastal/SharedMatting/

这个网页是算法的论文介绍页,可以从该网页下载到论文原文以及测试用图以及linux下的Demo。

  1. https://github.com/np-csu/AlphaMatting

我从该网页下载了Alpha Matting算法的c++源码。

  1. https://www.cnblogs.com/Imageshop/p/3550185.html

这是我在查询Alpha Matting算法资料时看见的比较友善的算法介绍。作者优化了C++版的算法。

我的实现效果

实验环境

系统: Windows 8.1 专业版

工具:Visual Studio 2017

Emgu:emgucv-windesktop 3.2.0.2682

C#测试工程: WPF工程项目

避免采坑

  1. 最好不要用最新版Vs2019

我刚开始采用VS2019,安装OpenCv后测试运行C++,各种不通。后续发现vs2019新建的项目自动配置为VC16 环境。 而下载的OpenCv明确指定了需要VC14或VC15. 如我下载的OpenCV: opencv-3.4.5-vc14_vc15.exe. 从名称即可看出。废了我许多不必要的尝试时间。

2、版本差异

刚开始下载OpenCV 最新的4.1.1 版本,报了很多类型错误。 建议使用3.* 的版本。  4.1.1版本我注释掉了部分OpenCv的代码,算法可以继续无差运行,但总感觉不完美,所以我替换成了3.* 的版本。

关键信息

C++类型

我处理成的对应c#类型

cv::Point

System.Drawing.Point

vector<cv::Point>&

List<System.Drawing.Point>

vector<vector<cv::Point>>&

List<List<System.Drawing.Point>>

char*

string

struct labelPoint

public class labelPoint

Tuple

public class TupleInfo

Ftuple

public class FtupleInfo

int**

Int[,]

uchar*

Byte[]

iterator

更改为For循环

Scalar

Emgu: MCvScalar

    public class labelPoint{public int x;public int y;public int label;};public class TupleInfo{public double FR;public double FG;public double FB;public double BR;public double BG;public double BB;public double sigmaf;public double sigmab;public int flag;};public class FtupleInfo{public double FR;public double FG;public double FB;public double BR;public double BG;public double BB;public double alphar;public double confidence;};public void loadImage(string sFile){pImg = CvInvoke.Imread(sFile);if (pImg.GetData() == null || pImg.GetData().Length == 0){Console.WriteLine("load pImg failed!");return;}height = pImg.Rows;width = pImg.Cols;step = pImg.Step / (pImg.ElementSize / pImg.NumberOfChannels);channels = pImg.NumberOfChannels;data = pImg.GetData();unknownIndex = new int[height, width];tri = new int[height, width];alpha = new int[height, width];}

有了这些对应信息,你就可以尝试自己移植了。

深化尝试

从我的调试结果来看,可以实现抠图,如果你也同时在C++环境下运行了算法,你会发现C#环境下的算法运行时间远超C++。然后我就考虑将抠图算法在C++环境下打包成dll供C#调用。

由于不熟悉c#与C++的交互,我踩了很多坑,实现的也并不算完美,不过总之调通了。

我将提前准备好的原图以及Trimap图的路径传给C++的dll,期望返回处理过后的Alpha数组。

c#端:

首先添加我生成的C++ Dll并声明引用。

[DllImport("ImgIntelligHelper.dll", CharSet = CharSet.Unicode)]

public extern static IntPtr GetMatteMap([MarshalAs(UnmanagedType.LPStr)] string sInput,

[MarshalAs(UnmanagedType.LPStr)] string sOutput);

然后对dll中的函数进行调用,返回透明度矩阵的内存地址,然后赋值到我创建的数组中。

// sInput - 原图路径; sTrimap: Trimap图路径

System.Drawing.Bitmap oBitmap = new Bitmap(sInput);

int nlength = oBitmap.Width * oBitmap.Height;

IntPtr intptr = GetMatteMap(sInput, sTrimap);

int[] arrAlpha = new int[nlength];

Marshal.Copy(intptr, arrAlpha, 0, nlength);

C++端:

新增了一个方法,将矩阵转换为int数组。

void AlphaMatting::GetAlphaMap()

{

int h = matte.rows;

int w = matte.cols;

Map = new int[h*w];

for (int i = 0; i < h; ++i)

{

for (int j = 0; j < w; ++j)

{

Map[i * w + j] = alpha[i][j];

}

};

}

// 接收图片并处理

int* GetMatteMap(char* sInput, char* sTrimap)

{

AlphaMatting alphaMatHelper;

alphaMatHelper.loadImage(sInput);

alphaMatHelper.loadTrimap(sTrimap);

alphaMatHelper.solveAlpha();

alphaMatHelper.GetAlphaMap();

return alphaMatHelper.Map;

}

最后用原图以及dll返回的Alpha数组实现抠图。 这是可行的方式,整个流程进行下来效率相对于纯C#版会有较大的改进。但是相对于纯C++版本来说,消耗还是过高。

然后我又尝试将C++版算法改成控制台应用程序。在C#中采用启动进程的方式,传入原图、Trimap图、输出图路径值,然后以不显示应用程序窗口的方式在后台静默执行。 进程结束后见到了C++应用程序处理过后的结果。

C#中调用C++生成的控制台应用exe。

private void DoConvert(string sIndex)

{

string sBasePath = AppDomain.CurrentDomain.BaseDirectory;

string sExeFile = sBasePath + @"\AlphaMattingPlugin.exe";

string sInput = sBasePath + @"\Datas\input" + sIndex+ ".jpg";

string sTrimap = sBasePath + @"\Datas\trimap" + sIndex + ".jpg";

string sOutput = sBasePath + @"\Datas\AlphaMattingPluginSample" + sIndex + ".png";

Process process = new Process();

process.StartInfo.FileName = sExeFile;

// 调用C++版本的控制台Exe,传入原图、Trimap图、抠图结果输出文件路径

process.StartInfo.Arguments = " " + sInput + " " + sTrimap + " " + sOutput;

process.StartInfo.CreateNoWindow = false;

process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

process.Start();

process.WaitForExit();

if (File.Exists(sOutput))

this.ShowImage(this.ImgResult, sOutput);

}

private void ShowImage(Image img, string sFile)

{

byte[] bytes = System.IO.File.ReadAllBytes(sFile);

BitmapImage bitImg = new BitmapImage();

bitImg.BeginInit();

bitImg.StreamSource = new System.IO.MemoryStream(bytes);

bitImg.EndInit();

bitImg.Freeze();

img.Source = bitImg;

}

这样处理后比纯C++环境多耗时0.5s左右,这个结论对于我是能接受的。

采用这种方式,抠图算法执行时间消耗我进行了测试,如下图

原来需要10-20s的现在仅用1-3s就能实现。如下图在C#环境下WPF工程调用C++版exe的调试截图:

结论

Alpha Matting抠图算法可以移植至C#平台,但是最佳实践还是用C++去处理,采用C#调用C++的方式会大大节省耗时。

图片越大耗时会越高,目前我尚未尝试4K图。

原本还想将Global Matting 及其他几种抠图算法也想法移植到C#平台,但是经过上文中一些列测试,发现还是保留原版本更为合理,用C#直接去调用Dll 或 包装的exe应用即可,而且效率更高。

源码下载:微信扫描下方二维码文章末尾获取链接。

c#实现SharedMatting抠图算法相关推荐

  1. 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting

    一.序言   陆陆续续的如果累计起来,我估计至少有二十来位左右的朋友加我QQ,向我咨询有关抠图方面的算法,可惜的是,我对这方面之前一直是没有研究过的.除了利用和Photoshop中的魔棒一样的技术或者 ...

  2. opencv 图像 抠图 算法_图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting

    一.序言 陆陆续续的如果累计起来,我估计至少有二十来位左右的朋友加我QQ,向我咨询有关抠图方面的算法,可惜的是,我对这方面之前一直是没有研究过的.除了利用和Photoshop中的魔棒一样的技术或者Ph ...

  3. 图像抠图算法学习 - Shared Sampling for Real-Time Alpha Matting

    本篇博文来自博主Imageshop,打赏或想要查阅更多内容可以移步至Imageshop. 转载自:https://www.cnblogs.com/Imageshop/p/3550185.html    ...

  4. 转载:图像抠图算法学习 -Shared Sampling for Real-Time Alpha Matting

    原文地址:https://www.cnblogs.com/Imageshop/p/3550185.html 一.序言   陆陆续续的如果累计起来,我估计至少有二十来位左右的朋友加我QQ,向我咨询有关抠 ...

  5. 掩膜区域内像素值_基于颜色空间采样的抠图算法

    摘 要: 由于自然图像抠图具有高度的不确定性,目前的抠图方法中对于前背景颜色较为复杂的图片处理效果并不理想.本文首先通过采集大量的样本对来估计初始的掩膜值,但是通过采样得到的样本对并不能很好地估计掩膜 ...

  6. opencv 图像 抠图 算法_opencv提取轮廓与抠图

    自然图像抠图/视频抠像技术梳理(image matting, video matting)-计算机视视觉专题1 图像抠图算法学习 - Shared Sampling for Real-Time Alp ...

  7. opencv 图像 抠图 算法_摄影领域的OpenCV教程之“蓝幕抠图”

    玩opencv时候,肯定会接触色彩空间.最常用的是RGB色彩空间,用0~255表示每个通道. 摄影投效里有个技术,叫做蓝幕,也有绿幕.后期把蓝色区域扣掉,然后换成别的背景. 在上图中,细心的小伙伴会发 ...

  8. ModNet抠图算法及摄像头实时抠图示例

    目录 一.视频抠图采用绿幕的原因 1.摄像机成色原因 2.抠图效果原因 3.经济成本 二.抠图背景知识 1.Trimap 2.什么是抠图 3.抠图算法分类 三.Deep Image Matting算法 ...

  9. 当PS遇上了AI:分割抠图算法总结

    说到抠图,我们更多人首先想到的是Photoshop.选定目标主体后,选择魔棒抠图.方框抠图.滤镜抠图.通道蒙版抠图等方法,根据待处理图像的特点,采取有针对性的手动方法,获得想要的抠图效果. 图1 PS ...

最新文章

  1. GAN的统一架构与WGAN
  2. 产生螺旋分类样本集合 SpiralData
  3. 03--MySQL自学教程:MySQL安装后的目录结构介绍和简单语法指令
  4. gzip, gunzip, zcat - 压缩或展开文件
  5. OneVPL与FFmpeg/GStreamer硬件编解码器
  6. LeetCode初级算法(数组)解答
  7. DevExpress.XtraGrid.Views.Grid.GridView 选中行焦点的滚动条的位置
  8. 语音识别(1)---语音识别(ASR)评估指标-WER(字错误率)和SER(句错误率)
  9. C语言 gcc API
  10. CSS——行内元素的margin与padding
  11. 前端直接读取文本文件内容
  12. react-native 修改app应用名称
  13. 6.3 交通工具类
  14. SaaS模式、技术与案例详解——第17章 案例详解
  15. 【动态规划】数字三角形c语言
  16. Win10鼠标点一下文件夹或文件没有选中的那个蓝色,但还是能正常用,比如双击跟右键,点一下也有详细信息
  17. kodi安卓4.0版及中文插件安装方法
  18. opencv--图像特征提取与描述
  19. 油猴脚本 from greasyfork
  20. 我不愿当一辈子啃老族

热门文章

  1. 【面经——广州道一云+笔试+一二三面+HR面+offer】
  2. (课程类 Course)
  3. Spark综合学习笔记(三)搜狗搜索日志分析
  4. html5动效系列二:超级惊艳 10款HTML5动画特效推荐
  5. Python推荐几个很不错的学习资源
  6. mysql查询and和or同时使用
  7. 新手从0-1的淘宝客创业之路 新手淘客必读
  8. R语言如何向向量中追加一个元素?
  9. 英特尔快速存储技术 linux,英特尔快速存储技术企业版(CTRL+I)RAID配置演示1
  10. 操作系统实验二实验报告