一、原理
两个方法:①两个高斯核两次加权实现,先对X卷积,后对结果进Y方向上的卷积
②直接用一个二维高斯核一次卷积
原理公式如图
模板窗口的大小一般采用1+2*ceil(3*nSigma) ceil是向上取整函数,例如ceil(0.6)=1。
卷积的意思就是图像中的点附近的模板大小区域乘以高斯模板区域,得到的结果就是该点卷积后的结果。卷积的核心意义就是获取原始图像中像模板特征的性质。
//////////////////////////////////////////////////////////////
//////////////////////////////高斯滤波////////////////////////
/////////////////////////////////////////////////////////////
double nSigma = 0.2;//因为在下面ceil(0.6)=1,定义高斯函数的标准差
//得到模板窗口大小
int nWindowSize = 1 + 2 * ceil(3 * nSigma);//sigma得到窗口大小,nsigma是高斯函数的标准差,选用的是3*3模板
//原因是因为高斯分布的数值在(μ—3σ,μ+3σ)的概率为0.9974所以选用3*3
int nCenter = nWindowSize / 2;//以模板的中心为原点
int nWidth = OpenCvGrayImage->width;//获取图像的像素宽度
int nHeight = OpenCvGrayImage->height;//获取图像的像素高度
IplImage * pCanny;
//用CreateImage函数创建图像首地址,并分配存储空间,将首地址赋给刚刚定义的数组
//为平滑后的图像分配内存
pCanny = cvCreateImage(cvGetSize(ColorImage), ColorImage->depth, 1);
//生成二维滤波核
double *pKernel_2 = new double[nWindowSize*nWindowSize];//定义一维高斯核数组
double d_sum = 0.0; //求和,进行归一化
double pai = 3.1415926;
for (int i = 0; i < nWindowSize; i++)//获取数据
{
for (int j = 0; j < nWindowSize; j++)
{
double n_Disx = i - nCenter;//水平方向距离中心像素距离
double n_Disy = i - nCenter;//垂直方向距离中心像素距离
pKernel_2[j*nWidth + i] = (exp(-0.5*(n_Disx*n_Disx + n_Disy*n_Disy) / (nSigma*nSigma))) / (2 * pai*nSigma*nSigma);
d_sum = d_sum + pKernel_2[j*nWindowSize + i];//求数值的和,方便归一化
}
}
for (int i = 0; i < nWindowSize; i++)//归一化处理
{
for (int j = 0; j < nWindowSize; j++)
{
pKernel_2[j*nWindowSize + i] = pKernel_2[j*nWindowSize + i] / d_sum;//归一化处理就是单个除以总和
}
}
//输出模板
for (int i = 0; i < nWindowSize*nWindowSize; i++)
{
if (i % (nWindowSize) == 0)
{
printf("\n");
}
printf("%.1f", pKernel_2[i]);
}
//滤波处理,采用高斯核进行高斯滤波,滤波后的数据保存在矩阵pCanny中
for (int s = 0; s < nWidth; s++)
{
for (int t = 0; t < nHeight; t++)
{
double dFilter = 0;
double dSum = 0;
//获取当前坐标(s,t)
//获取8邻域
for (int x = -nCenter; x <= nCenter; x++) //行
{
for (int y = -nCenter; y <= nCenter; y++) //列
{
if ((x + s >= 0) && (x + s < nWidth) && (y + t >= 0) && (y + t <= nHeight))//判断是否越界
{
double currentvalue = (double)OpenCvGrayImage->imageData[(y + t)*OpenCvGrayImage->widthStep + t + s];
dFilter += currentvalue*pKernel_2[x + nCenter + (y + nCenter)*nCenter];
dSum += pKernel_2[x + nCenter + (y + nCenter)*nCenter];
}
}
}
pCanny->imageData[t*pCanny->widthStep + s] = (uchar)(dFilter / dSum);
}
}
//显示高斯图
//cvNamedWindow("GaussImage", 0);
//cvShowImage("GaussImage",pCanny);
//cvWaitKey(0);
//cvDestroyWindow("GaussImage");