C#の達成SharedMattingマットアルゴリズム

入門

       C#の環境へのC ++のアルファマットマットアルゴリズムの移植版。OpenCVのC#バージョンEmguの主な用途は、OpenCVのC ++のサポートを交換してください。

 

参考資料

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

このページでは、ページの紙は、Linuxでオリジナルの紙海図やデモやテストにWebページからダウンロードすることができるアルゴリズムを記述しています。

https://github.com/np-csu/AlphaMatting
私は、このページからのC ++ソースコードアルファマットアルゴリズムをダウンロードしました。

https://www.cnblogs.com/Imageshop/p/3550185.html
これは私がお問い合わせアルファマットアルゴリズムデータ友好アルゴリズム記述で見たものです。アルゴリズムのC ++版の最適化。

 

私は効果を実現しました

 

実験環境

システム:Windows 8.1 Professional Editionの

ツール:Visual Studioの2017

Emgu:emgucv-windesktop 3.2.0.2682

C#のテストプロジェクト:WPFプロジェクト

 

ピットを避けます

  1. ベストVs2019の最新バージョンを使用しません

  私は、インストールOpenCVのテストランC ++、様々な不合理後、VS2019を使用して開始しました。フォローvs2019新しいプロジェクトが自動的に設定されたVC16環境を発見しました。... OpenCVの-3.4.5-vc14_vc15.exeは、名前から見ることができます:私はOpenCVのをダウンロードして、ダウンロードOpenCVのは、明示的に必要性のVC14またはVC15を指定します。私がしようとする不必要な多くの時間を費やしました。

         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図を試してみてください。

        もともと私は、グローバル・マットマットとC#のプラットフォームの考え方に移植され、いくつかの他のアルゴリズムをしたいが、上に挙げたいくつかのテストの後、まだ元のバージョンを保持することはexeファイルにC#DLLまたはパッケージ化されたアプリケーションを使用して、直接呼び出すことがより合理的であるましたそして、より効率的。

        ソースのダウンロード:Fanger魏コードスキャンマイクロ文字の下に記事の最後にあるリンクを取得します。

                                 

おすすめ

転載: www.cnblogs.com/duel/p/removebg.html