canny的高斯滤波

一、原理

两个方法:①两个高斯核两次加权实现,先对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");

猜你喜欢

转载自blog.csdn.net/tudoufanqietudou/article/details/82429868
今日推荐