【使用EmguCV进行图像处理】导向滤波

最近做一些图像处理的工作,搜寻资料发现很多大家都推荐导向滤波,不过这类大都是opencv的代码较多,所以我仿照网上的一些资料转了一份C#版本,如有错误请指正,互相交流学习。

开发环境:vs2017,win10。EmguCV通过“项目→管理NuGet程序包”,搜索emgucv导入即可。

代码如下:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;

public static class PictureProcessing
{
    public static Bitmap GuidedFilter(Mat srcMat, Mat guidedMat, int radius, double eps)
    {
        //------------【0】转换源图像信息,将输入扩展为64位浮点型,以便以后做乘法------------
        srcMat.ConvertTo(srcMat, DepthType.Cv64F);
        guidedMat.ConvertTo(guidedMat, DepthType.Cv64F);

        //--------------【1】各种均值计算----------------------------------
        Mat mean_p = new Mat();
        Mat mean_I = new Mat();
        Mat mean_Ip = new Mat();
        Mat mean_II = new Mat();

        CvInvoke.BoxFilter(srcMat, mean_p, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));//生成待滤波图像均值mean_p
        CvInvoke.BoxFilter(guidedMat, mean_I, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));//生成引导图像均值mean_I

        Mat sg = new Mat();
        Mat gg = new Mat();
        CvInvoke.Multiply(srcMat, guidedMat, sg);
        CvInvoke.Multiply(guidedMat, guidedMat, gg);

        CvInvoke.BoxFilter(sg, mean_Ip, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));//生成互相关均值mean_Ip
        CvInvoke.BoxFilter(gg, mean_II, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));//生成引导图像自相关均值mean_II

        //--------------【2】计算相关系数,计算Ip的协方差cov和I的方差var------------------
        Mat cov_Ip = new Mat();
        Mat Ip = new Mat();
        CvInvoke.Multiply(mean_I, mean_p, Ip);
        CvInvoke.Subtract(mean_Ip, Ip, cov_Ip);

        Mat var_I = new Mat();
        Mat II = new Mat();
        CvInvoke.Multiply(mean_I, mean_I, II);
        CvInvoke.Subtract(mean_II, II, var_I);

        //---------------【3】计算参数系数a、b-------------------
        Mat a = new Mat();
        Mat b = new Mat();

        Mat I_eps = new Mat();
        CvInvoke.Add(var_I, new ScalarArray(eps), I_eps);
        CvInvoke.Divide(cov_Ip, I_eps, a);

        Mat aI = new Mat();
        CvInvoke.Multiply(a, mean_I, aI);
        CvInvoke.Subtract(mean_p, aI, b);

        //--------------【4】计算系数a、b的均值-----------------
        Mat mean_a = new Mat();
        Mat mean_b = new Mat();
        CvInvoke.BoxFilter(a, mean_a, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));
        CvInvoke.BoxFilter(b, mean_b, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));

        //---------------【5】生成输出矩阵------------------
        Mat axsrc = new Mat();
        CvInvoke.Multiply(mean_a, srcMat, axsrc);

        Mat dstImage = new Mat();
        CvInvoke.Add(axsrc, mean_b, dstImage);

        mean_p.Dispose();
        mean_I.Dispose();
        mean_Ip.Dispose();
        mean_II.Dispose();
        sg.Dispose();
        gg.Dispose();
        cov_Ip.Dispose();
        Ip.Dispose();
        var_I.Dispose();
        II.Dispose();
        a.Dispose();
        b.Dispose();
        I_eps.Dispose();
        aI.Dispose();
        mean_a.Dispose();
        mean_b.Dispose();
        axsrc.Dispose();

        return dstImage.Bitmap;
    }
}

使用时直接调用:

Mat src = new Mat(openFileDialog.FileName);

pictureBox1.Image = PictureProcessing.GuidedFilter(src, src, 50, 300);

主要就是参数radius和eps的配置,看自己喜好。网上亦有很多改进效率的方法,还在琢磨中。

参考资料:https://blog.csdn.net/sinat_36264666/article/details/77990790

你可能感兴趣的:(emgucv)