【学习opencv】高斯滤波及其实现

来源:互联网 发布:学校网上缴费软件 编辑:程序博客网 时间:2024/05/16 07:21

高斯滤波及其实现

  • 创建高斯滤波核
  • 用滑动窗体进行卷积滤波

1.创建高斯滤波核

高斯滤波模板是通过二维高斯函数计算出来的:

G(x,y)=12πσ2ex2+y22σ2

高斯模板需要知道模板大小及σ值,再通过上述高斯函数来确定模板系数。例现有3x3高斯模板如下,以模板中心为坐标原点,其高斯函数中的x2+y2就是指模板在坐标系中离原点的距离。

模板的分类:有小数模板和整数模板
小数模板计算方法:利用高斯分布函数求得后,对其中每个元素的值除以模板系数和.
整数模板计算方法:利用高斯分布函数求得后,先归一化(左上角的元素为1),取整,再乘以模板取整后的系数和。

Note:高斯模板的大小与σ的选择:高斯核的宽度应该为方差σ的3倍,原理是因为高斯正态分布中的3σ原则。

2.用滑动窗体进行卷积滤波

Note:注意3通道的卷积运算,是分别选取该通道的进行运算。

效果

这里写图片描述

代码:

#include<opencv2/opencv.hpp>#include<iostream>#include<math.h>using namespace std;using namespace cv;/**生成高斯滤波的模板*function return 整型模板@param: windowsize 模板的大小 奇数@param: sigma 方差的大小*/vector<vector<int>> createGussInt(int windowsize,double sigma){    /*计算小数模板    *此时计算出来的小数模板不能直接用于高斯滤波,还需要进一步处理    */    vector<vector<double> > GussinDouble(windowsize, vector<double>(windowsize));    int std = windowsize / 2;    for (int i = 0; i < windowsize; i++)    {        for (int j = 0; j < windowsize; j++)        {            int tem = (i - std)*(i - std) + (j - std)*(j - std);            //GussinDouble[i][j] = (1 / 2.0*pi*sigma)*exp(-tem / (2.0*sigma*sigma));            GussinDouble[i][j] =exp(-tem / (2.0*sigma*sigma));            cout << GussinDouble[i][j] << " ";            if (j == windowsize - 1)cout << "\n";        }    }    //变为整数模板:归一化,向下取整    double k = 1 / GussinDouble[0][0];    vector<vector<int>>GussinInt(windowsize, vector<int>(windowsize));    for (int i = 0; i < windowsize; i++)    {        for (int j = 0; j < windowsize; j++)        {            GussinDouble[i][j] = GussinDouble[i][j] * k;            GussinInt[i][j] = floor(GussinDouble[i][j]);            cout << GussinInt[i][j] << " ";            if (j == windowsize - 1)cout << "\n";        }    }    return GussinInt;}/**高斯滤波**采用滑动模板窗口的方法滤波处理图片,图片最外层因为滤波窗口的大小会出现没有计算的情况,这里选用opencv自带的边界扩展函数@param: img 支持单通道和3通道的输入图像@param: kernel 整型滤波核*/void Guss(Mat src,Mat &dst,vector<vector<int>>kernel){    cout << "src.rows" << src.rows << endl;    cout << "src.cols" << src.cols << endl;    int std = kernel.size()/2;    Mat tem;    copyMakeBorder(src,tem,std,std,std,std, BORDER_REPLICATE);    cout << "tem col:" << tem.cols << endl;    cout << "tem.rows:" << tem.rows << endl;    cout << "tem channels:" << tem.channels() << endl;    uchar *p = tem.data;    int step = tem.step[0];    int channels = tem.channels();    for (int i = std; i < tem.rows-std; i++)    {        for (int j = std*channels; j < (tem.rows - std)*channels; j = j + channels)//保证一列的遍历        {            double sum[3] = { 0 };            for (int m = -std; m <= std; m++)            {                for (int n = -std; n <= std; n++)                {                    if(channels==1)sum[0]+= p[(i + m)*step + j + n] * kernel[std + m][std + n];                    if (channels == 3) {                        sum[0] += p[(i + m)*step + j + n*channels] * kernel[std + m][std + n];                        sum[1] += p[(i + m)*step + j+1 + n*channels] * kernel[std + m][std + n];                        sum[2] += p[(i + m)*step + j+2 + n*channels] * kernel[std + m][std + n];                    }                }            }            //饱和处理        /*  for (int i = 0; i < 3; i++)            {                if (sum[i] > 255)sum[i] = 255;                else if (sum[i] < 0)sum[0] = 0;            }*/            //赋值            if (channels == 1)p[i*step + j] = sum[0];            if (channels == 3) {                p[i*step + j] = sum[0];                p[i*step + j + 1] = sum[1];                p[i*step + j + 2] = sum[2];            }        }    }    //range左包含右不包含    dst = tem(Range(std, tem.rows - std),Range(std, tem.cols - std));}/*主函数*/int main(){    Mat img = imread("test.jpg",1);    vector<vector<int>>kernel;    kernel=createGussDouble(3,0.8);    Mat dst;    imshow("img",img);    Guss(img, dst,kernel);    imshow("dst",dst);    waitKey(0);}
原创粉丝点击