高斯模糊是一个两维空间的卷积模糊操作,在图像去噪方面有着非常好的效果。
一维高斯函数如下:其中x∈[-n,n],sigma代表标准方差,通常取值1。
步骤如下:
一、调用get2DKernalData算出高斯内核数据
代码:
#include "math.h"
using namespace std;
#define pi 3.1415926535898
float* get1DKernalData(int n,float sigma)
{
float sigma22=2*sigma*sigma;
float pi2=2*(float)pi;
float sqrtSigmaPi2=(float)sqrt(pi2)*sigma;
float* kernalData=new float[2*n+1];
int index=0;
for(int i=-n; i<=n; i++)
{
float distance=i*i;
kernalData[index]=(float)exp((-distance)/sigma22)/sqrtSigmaPi2;
index++;
}
return kernalData;
}
二维高斯函数如下:
代码:
float** get2DKernalData(int n,float sigma)
{
int size = 2*n +1;
float sigma22 = 2*sigma*sigma;
float sigma22PI = (float)pi * sigma22;
float** kernalData = new float*[size];
for(int i=0; i<size; i++)
{
kernalData[i]=new float[size];
}
int row = 0;
for(int i=-n; i<=n; i++)
{
int column = 0;
for(int j=-n; j<=n; j++)
{
float xDistance = i*i;
float yDistance = j*j;
kernalData[row][column] = (float)exp(-(xDistance + yDistance)/sigma22)/sigma22PI;
column++;
}
row++;
}
return kernalData;
}
二、将高斯内核数据传入到convolutionFilte方法中计算卷积,得出峰值和峰值比率,最后进行归一化处理得到高斯卷积图像
Mat Convolution::convolutionFilte(Mat* m_opt,Mat* m_src,Mat* m_dst,int dst_size)
{
Mat opt=((Mat)*m_opt);
Mat src=((Mat)*m_src);
Mat dst=((Mat)*m_dst);
for(int row=0; row<src.rows; row++)
{
for(int col=0; col<src.cols; col++)
{
float wSum = 0.0;
float rSum=0,gSum=0,bSum=0;
for(int subRow=0; subRow<opt.rows; subRow++)
{
for(int subCol=0; subCol<opt.cols; subCol++)
{
bSum += src.at<Vec3b>(row,col)[0] * opt.at<float>(subRow,subCol);
gSum += src.at<Vec3b>(row,col)[1] * opt.at<float>(subRow,subCol);
rSum += src.at<Vec3b>(row,col)[2] * opt.at<float>(subRow,subCol);
wSum += opt.at<float>(subRow ,subCol);
}
}
dst.at<Vec3b>(row,col)[0] = (int)(bSum / wSum);
dst.at<Vec3b>(row,col)[1] = (int)(gSum / wSum);
dst.at<Vec3b>(row,col)[2] = (int)(rSum / wSum);
}
}
///计算峰值
int srcpeak = 0;
int dstPeak = 0;
for(int row=0; row<src.rows; row++)
{
for(int col=0; col<src.cols; col++)
{
if(srcpeak < src.at<Vec3b>(row,col)[0])
{
srcpeak = src.at<Vec3b>(row,col)[0];
}
if(srcpeak < src.at<Vec3b>(row,col)[1])
{
srcpeak = src.at<Vec3b>(row,col)[1];
}
if(srcpeak < src.at<Vec3b>(row,col)[2])
{
srcpeak = src.at<Vec3b>(row,col)[2];
}
if(dstPeak < dst.at<Vec3b>(row,col)[0])
{
dstPeak = dst.at<Vec3b>(row,col)[0];
}
if(dstPeak < dst.at<Vec3b>(row,col)[1])
{
dstPeak = dst.at<Vec3b>(row,col)[1];
}
if(dstPeak < dst.at<Vec3b>(row,col)[2])
{
dstPeak = dst.at<Vec3b>(row,col)[2];
}
}
}
/// 归一化处理
double rate = ((double) srcpeak) / ((double)dstPeak);
for(int row=0; row<src.rows; row++)
{
for(int col=0; col<src.cols; col++)
{
dst.at<Vec3b>(row,col)[0] = (int)(rate * dst.at<Vec3b>(row,col)[0]);
dst.at<Vec3b>(row,col)[1] = (int)(rate * dst.at<Vec3b>(row,col)[1]);
dst.at<Vec3b>(row,col)[2] = (int)(rate * dst.at<Vec3b>(row,col)[2]);
}
}
return dst;
}