均值 、高斯、双边 算法实现(opencv 、halcon)

3 篇文章 0 订阅
1 篇文章 0 订阅

在滤波算法中,均值、高斯、双边都是常用的算法,知道他们用途的同时,再了解它们的底层原理,有助于对图像算法的理解和算法的底层优化。

本文介绍这三种算法,并给出底层的实现代码(不同的实现方式),和实现的效果展示,和一些库函数的效果对比。

本文为转载文章:

代码实现参考了以下链接:

https://blog.csdn.net/u013921430/article/details/84532068?spm=1001.2014.3001.5506

https://blog.csdn.net/a435262767/article/details/107115249

均值滤波:

介绍:均值滤波是求邻域内的均值作为新的像素值。

实现:采用c#数组的形式实现均值滤波算法,对于边缘像素不进行填充,而是取有值的点进行平均。

首先生成一个0-255的随机数二维数组,再求每一个像素位置的滤波后的值(针对边缘位置进行分类讨论)


public bool Mean_ilter( int size, int imgsize,out double[,] resImg,out HObject image)
{
            //声明一个halcon图像用于显示
            image = null;
            HOperatorSet.GenEmptyObj(out image);      
            HOperatorSet.GenImageConst(out image ,"byte", imgsize*1.0, imgsize*1.0);

            //默认是滤波器的尺寸是3
            size = 3;
            //首先生成一个随机数矩阵
            Random rd = new Random();
            double[,] ImgSource = new double[imgsize, imgsize];
            for (int i = 0; i < imgsize; i++)
            {
                for (int j = 0; j < imgsize; j++)
                {
                    double x = rd.Next(255);
                    ImgSource[i, j] = x;

                    HOperatorSet.SetGrayval(image,i,j,x);

                  //  System.Console.Write("  ");
                  //  System.Console.Write(ImgSource[i, j]);
                }
                System.Console.WriteLine();
            }
            resImg = new double[imgsize,imgsize];

            //进行均值滤波处理
            for(int m=0;m<imgsize;m++)
            {
                for(int n=0;n<imgsize;n++)
                {
                    //对于边界的像素单独处理
                    if(n==0&&m==0)
                    {
                        //左上角
                        resImg[m, n] = (ImgSource[m, n] +ImgSource[m, n + 1]  + 
                            ImgSource[m + 1, n] + ImgSource[m + 1, n + 1]) / 4;
                    }
                    else if (n == (imgsize -1)&& m == 0)
                    {
                        //右上角
                        resImg[m, n] = ( ImgSource[m, n - 1] + ImgSource[m, n] +
                             ImgSource[m + 1, n - 1] + ImgSource[m + 1, n] ) / 4;
                    }
                    else if (n == 0 && m == (imgsize - 1))
                    {
                        //左下角
                        resImg[m, n] = (ImgSource[m - 1, n] + ImgSource[m - 1, n + 1] +ImgSource[m, n] +
                            ImgSource[m, n + 1] ) / 4;
                    }
                    else if (m == (imgsize - 1) && n == (imgsize - 1))
                    {
                        //右下角
                        resImg[m, n] = (ImgSource[m - 1, n - 1] + ImgSource[m - 1, n] + 
                            ImgSource[m, n - 1] + ImgSource[m, n] ) / 4;
                    }
                    else if ( m == 0)
                    {
                        //非角落,第一行
                        resImg[m, n] = ( ImgSource[m, n - 1] + ImgSource[m, n] +
                            ImgSource[m, n + 1] + ImgSource[m + 1, n - 1] + ImgSource[m + 1, n] + ImgSource[m + 1, n + 1]) / 6;
                    }
                    else if (m == (imgsize - 1))
                    {
                        //非角落,最后一行
                        resImg[m, n] = (ImgSource[m - 1, n - 1] + ImgSource[m - 1, n] + ImgSource[m - 1, n + 1] + ImgSource[m, n - 1] + ImgSource[m, n] +
                            ImgSource[m, n + 1] ) / 6;
                    }
                    else if (n == 0)
                    {
                        //非角落,第一列
                        resImg[m, n] = ( ImgSource[m - 1, n] + ImgSource[m - 1, n + 1] +  ImgSource[m, n] +
                            ImgSource[m, n + 1] + ImgSource[m + 1, n] + ImgSource[m + 1, n + 1]) / 6;
                    }
                    else if (n == (imgsize - 1))
                    {
                        //非角落,最后一列
                        resImg[m, n] = (ImgSource[m - 1, n - 1] + ImgSource[m - 1, n] +  ImgSource[m, n - 1] + ImgSource[m, n] +
                             ImgSource[m + 1, n - 1] + ImgSource[m + 1, n] ) / 6;
                    }
                    else
                    {
                        //中间部分
                        resImg[m, n] = (ImgSource[m-1,n-1]+ ImgSource[m-1, n]+ ImgSource[m-1, n+1]+ ImgSource[m, n-1]+ ImgSource[m, n]+ 
                            ImgSource[m, n+1]+ ImgSource[m+1, n-1] + ImgSource[m+1, n] + ImgSource[m+1, n+1])/ 9;
                    }
                }
            }          
            return true;
}

高斯滤波:

介绍:高斯滤波是求邻域的加权均值作为新的像素值,以到像素点的距离进行权重的分配。当窗口大小确定时,滤波核是固定的

实现:

方法1:采用halcon的方式进行实现,(自实现的边缘填充。

计算卷积核的函数ComPut_Gauss_ConvKernel   参考我之前的文章:

https://blog.csdn.net/qq_53863660/article/details/136842479?spm=1001.2014.3001.5502

此方法实现比较呆,只可以实现 3*3size的滤波,先进行了边缘填充,选择靠近的像素值进行填充,然后循环整个图像,在扩充图像上进行计算,得到每一个位置的滤波像素值

public bool  gaussFilter(int _size,HObject image,out HObject GaussImg)
{
          // HOperatorSet.Rgb1ToGray(image,out image);只适用于灰度图
          // 初始化halcon对象
            GaussImg = null;  HObject ExpandImage = null;
            HOperatorSet.GenEmptyObj(out GaussImg);           
            HOperatorSet.GenEmptyObj(out ExpandImage);

            //根据尺寸,计算卷积核
            double[,] matrix = new double[_size,_size];
            ComPut_Gauss_ConvKernel(_size, 1.5, out  matrix);

            //生成结果图和扩充图
            HOperatorSet.GetImageSize(image, out HTuple width, out HTuple height);
            HOperatorSet.GenImageConst(out GaussImg, "byte", width, height);
            HOperatorSet.GenImageConst(out ExpandImage,"byte",width.D+2.0,height.D+2.0);
            //原图的宽高
            int H = height.I;
            int W = width.I;
            //扩充图的宽高
            int H_Epd = H + 2;
            int W_Epd = W + 2;

            //填充规则,角落的位置填充角落的像素,非角落的像素填充靠近的像素
            double grayValue1=0;
            for (int i=0;i< H_Epd; i++)
            {
                for(int j=0;j< W_Epd; j++)
                {
                    //左上角
                    if(i==0&&j==0)
                    {
                        HOperatorSet.GetGrayval(image,i,j,out HTuple gray);
                        grayValue1 = gray.D;
                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }
                    //右下角
                    else if(i==H_Epd-1&&j==W_Epd-1)
                    {
                        HOperatorSet.GetGrayval(image, H-1, W-1, out HTuple gray);
                        grayValue1 = gray.D;

                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }
                    //左下角
                    else if(i == H_Epd-1 && j == 0)
                    {
                        HOperatorSet.GetGrayval(image, H - 1, 0, out HTuple gray);
                        grayValue1 = gray.D;

                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }
                    //右上角
                    else if(i == 0 && j == W_Epd - 1)
                    {
                        HOperatorSet.GetGrayval(image, 0, W-1, out HTuple gray);
                        grayValue1 = gray.D;

                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }
                    //第一行非角落
                    else if (i == 0 )
                    {
                        HOperatorSet.GetGrayval(image, i-1+1, j-1, out HTuple gray);
                        grayValue1 = gray.D;

                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }
                    //最后一行非角落
                    else if (i == H_Epd-1)
                    {
                        HOperatorSet.GetGrayval(image, i - 1-1 , j - 1, out HTuple gray);
                        grayValue1 = gray.D;

                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }
                    //第一列非角落
                    else if (j == 0)
                    {
                        HOperatorSet.GetGrayval(image, i - 1 , j - 1 + 1, out HTuple gray);
                        grayValue1 = gray.D;

                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }
                    //最后一列非角落
                    else if (j==W_Epd-1)
                    {
                        HOperatorSet.GetGrayval(image, i - 1 , j - 1-1, out HTuple gray);
                        grayValue1 = gray.D;

                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }
                    //中间位置
                    else
                    {
                        HOperatorSet.GetGrayval(image, i - 1 , j - 1, out HTuple gray);
                        grayValue1 = gray.D;

                        HOperatorSet.SetGrayval(ExpandImage, i, j, grayValue1);
                    }                   
                }
            }

            //以扩充图为基准,进行滤波计算,得到高斯结果图
            double grayValue2;         
            for(int i=0;i< H; i++)
            {
                for(int j=0;j< W; j++)
                {
                    //卷积核第一行
                    HOperatorSet.GetGrayval(ExpandImage, i+1-1, j+1-1, out HTuple gray1);
                    HOperatorSet.GetGrayval(ExpandImage, i+1-1, j+1, out HTuple gray2);
                    HOperatorSet.GetGrayval(ExpandImage, i+1-1, j+1+1, out HTuple gray3);

                    //卷积核第二行
                    HOperatorSet.GetGrayval(ExpandImage, i+1, j+1-1, out HTuple gray4);
                    HOperatorSet.GetGrayval(ExpandImage, i+1, j+1, out HTuple gray5);
                    HOperatorSet.GetGrayval(ExpandImage, i+1, j+1+1, out HTuple gray6);

                    //卷积核第三行
                    HOperatorSet.GetGrayval(ExpandImage, i+1+1, j+1-1, out HTuple gray7);
                    HOperatorSet.GetGrayval(ExpandImage, i+1+1, j+1, out HTuple gray8);
                    HOperatorSet.GetGrayval(ExpandImage, i+1+1, j+1+1, out HTuple gray9);

                    //此处可以采用halcon自带的卷积运算算子,可以优化速度

                    grayValue2 = gray1.D * matrix[0,0] + gray2.D * matrix[0, 1] + gray3.D * matrix[0, 2] + gray4.D * matrix[1, 0] + 
                    gray5.D * matrix[1, 1] + gray6.D * matrix[1, 2] + gray7.D * matrix[2, 0] + gray8.D * matrix[2, 1] + gray9.D * matrix[2, 2];

                    HOperatorSet.SetGrayval(GaussImg, i, j, grayValue2);
                }
            }

            ExpandImage.Dispose();
            return true;
}

 方式2:采用CV的方式

直接采用opencv的卷积函数进行计算,方便快捷。

public bool gaussFilterUsingOpencv(int _size,Mat img,out Mat imgGauss)
{
            imgGauss = new Mat();
            double[,] matrix = new double[_size, _size];
            ComPut_Gauss_ConvKernel(_size, 10, out matrix);

            //边缘扩充函数
            //将c#数组矩阵转换为mat类型
            Mat kernel = new Mat(_size, _size, MatType.CV_64F, matrix, 0);
            //直接采用cv只带的相关运算,自带了扩充功能
            Cv2.Filter2D(img, imgGauss,MatType.CV_8UC1,kernel,new Point(-1,-1),0,BorderTypes.Replicate);

            return true;
}

双边滤波:

介绍:双边滤波是也是求邻域的加权均值作为新的像素值,以到像素点的距离和像素值的相似性进行权重的分配。当窗口大小确定时,滤波核也不确定

实现:

此方法可以适应所有的size,

1.先对图像进行扩充

2.循环处理每一个像素

3.针对每一个像素,又循环处理该像素每一个滤波核的位置,分别计算距离和像素值权重(在扩充图进行计算),得到权重,直接计算该位置权重后的值,并进行叠加。

4.计算完并叠加所有滤波核位置的权重后的值之后,进行归一化处理(除以权重和),再赋值给该位置,作为该像素位置滤波后的像素值。

5.循环处理

距离权重:D_{w}=x^{2}+y^{2}

像素值相似权重:V_{w}=(src(i,j)-expand(,))^{2}

综合权重:W=\exp (-\frac{D_{w}}{2*sigma_{d}^{2}})*\exp (-\frac{V_{w}}{2*sigma_{v}^{2}})

//采用opencv的库自实现的双边滤波
        public bool bilaFilter(Mat img ,int size,double sigmaD,double sigmaV,out Mat imgBila)
        {
            int imgWidth =img.Cols;
            int imgHeight =img.Rows;

            //初始化结果图像
            imgBila = new Mat(img.Rows,img.Cols,MatType.CV_8UC1,new Scalar(0));
            Mat imgExpand = new Mat();

            //对原图进行边界扩充处理
            Cv2.CopyMakeBorder(img,imgExpand,(int)(size/2), (int)(size / 2), (int)(size / 2), (int)(size / 2),BorderTypes.Replicate);
            //循环处理,计算滤波后图像每一个像素点的值
            for(int i=0;i<imgHeight;i++)
            {
                for(int j=0;j<imgWidth;j++)
                {
                    double weightSum = 0;
                    double pixelValue = 0;

                    //循环处理,对滤波核的每一个网格进行处理
                    for(int row_w=-(size/2);row_w<(size/2);row_w++)
                    {
                        for(int col_w=-(size/2);col_w<(size/2);col_w++)
                        {
                            //计算高斯距离权重
                            double dist_square = Math.Pow(col_w,2) + Math.Pow(row_w,2);
                            //计算像素值相似度权重
                            //采用C#  opencv获取像素值的时候,此处的类型必须是byte

                            double value_square = Math.Pow(img.At<byte>(i, j) 
                            - imgExpand.At<byte>(i+(int)(size/2)- col_w, j+(int)(size/2) + row_w), 2);//此处-row_w,再+col_w应该也可以,看怎么去定义滤波窗口的窗口坐标,但是不论写哪一种,下面p1行(注释处)应该和此处保持一致

                            //距离和像素权重相乘得到该位置的权重
                            double weight = Math.Exp(-(dist_square/(2*sigmaD*sigmaD)+value_square/(2*sigmaV*sigmaV)));
                            //计算权重和
                            weightSum += weight;
                            //计算权重计算后的值
                            pixelValue += weight * imgExpand.Get<byte>(i + (size / 2) - col_w, j + (size / 2) + row_w);//p1                           
                        }
                    }
                    //归一化,得到该位置滤波后的像素值
                    imgBila.Set<byte>(i, j,(byte)(pixelValue/weightSum));
                }
            }
            return true;
        }

效果和效果:

yi.原图

2.高斯滤波

①  使用opencv自实现的高斯滤波                                                ②    opencv自带的高斯滤波函数                                                                                     

 ③ 使用halcon自实现的高斯滤波(size 3)                                  ④halcon自带的高斯滤波(size 3)

3.均值滤波

①  halcon自带的均值滤波函数                                                  ②  原图                                                          ③均值滤波结果(自实现的c#数组的方式)

4.双边滤波

  

①    自实现的双边滤波效果(采用opencv)                                  ②opencv自带的双边滤波函数效果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 很抱歉,我是一名语言模型AI,无法提供代码实现。但是,我可以告诉您,OpenCVHalcon都是计算机视觉领域的常用工具,可以用于图像处理、目标检测、图像识别等方面。如果您想使用OpenCV实现Halcon算法,可以先了解Halcon算法的原理和实现方式,然后使用OpenCV的相关函数和库进行编程实现。同时,也可以参考一些相关的教程和案例,加深对OpenCVHalcon的理解和应用。 ### 回答2: Halcon算法是一种被广泛应用的机器视觉算法,其在工业视觉、医学影像等领域都有广泛的应用。而OpenCV是一款开源的计算机视觉库,提供了丰富的图像处理和分析工具。因此,将Halcon算法应用于OpenCV中,不仅可以充分利用OpenCV的图像处理能力,还可以拥有Halcon算法的强大功能,实现更高效、精准的图像处理。 要实现Halcon算法,需要对于Halcon算法的相关知识有一定的了解。首先,需要了解Halcon算法的特点和主要应用。其次,需要了解OpenCV的基本操作方法和常用函数,如图像读取、图像处理、滤波等操作。然后,需要将Halcon算法OpenCV进行结合,根据具体的应用场景,选择合适的Halcon算法进行调用,实现图像处理和分析。 具体实现过程可以分为以下几步: 1. 首先,使用OpenCV读取图像,将图像数据存储在CV::Mat数据结构中。然后,将CV::Mat数据结构转换为Halcon图像数据结构。 2. 在Halcon中进行图像处理和分析。根据需求选择合适的Halcon算法进行调用,如形状匹配、特征提取、图像分类等。 3. 将Halcon处理结果返回到OpenCV中。可以将Halcon结果存储为CV::Mat数据结构,以便后续OpenCV操作使用。 4. 最后,根据具体需求,使用OpenCV对处理结果进行后续处理和分析。 需要注意的是,在使用Halcon算法的同时,要考虑到Halcon算法的复杂性和计算量。在实际应用中,应该根据具体情况灵活选择算法并调整参数,以保证算法的高效和准确性。 综上所述,使用OpenCV实现Halcon算法可以充分发挥两者的优势,实现高效、准确的图像处理和分析,适用于各种机器视觉和图像分析领域的应用。 ### 回答3: OpenCVHalcon都是图像处理领域广泛使用的开源软件库,它们都提供了一系列的算法实现各种图像处理任务,例如图像滤波、边缘检测、物体识别等。 HACON是一款针对工业领域图像处理的软件,而OpenCV则更加通用。在工业领域,Halcon有其不可替代的优势,因此有时候需要使用Halcon提供的算法,但是由于Halcon本身是商业软件,需要购买授权才能使用,因此很多人会选择使用OpenCV实现Halcon中的一些算法实现Halcon算法的一个常见做法是使用OpenCV的C++接口,通过编写一些桥接代码来转换Halcon算法OpenCV的数据格式,使得OpenCV能够调用Halcon算法进行处理。具体来说,我们需要在OpenCV中为每一个Halcon算法编写一个相应的函数或类,以便OpenCV能够以类似于调用OpenCV函数的方式来使用Halcon算法。 例如,我们要实现Halcon中的模板匹配算法。首先,我们需要将Halcon中的模板图像和待匹配图像转换为OpenCV的Mat类型(即OpenCV中的图像数据存储格式)。同时,我们也需要将Halcon中的参数转换为对应的OpenCV参数。然后,我们可以调用Halcon提供的模板匹配函数进行处理,之后再将Halcon的结果转换为OpenCV的数据类型,并返回给OpenCV调用者。 需要注意的是,使用OpenCV实现Halcon算法需要对两个库都非常熟悉,并具有深厚的图像处理经验。由于HalconOpenCV的设计思路和接口不同,因此在实现Halcon算法时需要考虑到数据类型的转换、参数的正确性以及算法流程的实现等细节。因此,使用OpenCV实现Halcon算法需要有一定的技术储备和实践经验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值