()高斯理论简介
()
()代码实现
四 使用高斯滤波器进行图像的平滑
()高斯简介
http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html 阮一峰
生成高斯核
/*************************************************************************
*
* \函数名称:
* MakeGauss()
*
* \输入参数:
* double sigma - 高斯函数的标准差
* double **pdKernel - 指向高斯数据数组的指针
* int *pnWindowSize - 数据的长度
*
* \返回值:
* 无
*
* \说明:
* 这个函数可以生成一个一维的高斯函数的数字数据,理论上高斯数据的长度应
* 该是无限长的,但是为了计算的简单和速度,实际的高斯数据只能是有限长的
* pnWindowSize就是数据长度
*
*************************************************************************
*/
void MakeGauss(double sigma, double **pdKernel, int *pnWindowSize)
{
// 循环控制变量
int i ;
// 数组的中心点
int nCenter;
// 数组的某一点到中心点的距离
double dDis ;
double PI = 3.14159;
// 中间变量
double dValue;
double dSum ;
dSum = 0 ;
// 数组长度,根据概率论的知识,选取[-3*sigma, 3*sigma]以内的数据。
// 这些数据会覆盖绝大部分的滤波系数
*pnWindowSize = 1 + 2 * ceil(3 * sigma);
// 中心
nCenter = (*pnWindowSize) / 2;
// 分配内存
*pdKernel = new double[*pnWindowSize] ;
for(i=0; i< (*pnWindowSize); i++)
{
dDis = (double)(i - nCenter);
dValue = exp(-(1/2)*dDis*dDis/(sigma*sigma)) / (sqrt(2 * PI) * sigma );
(*pdKernel)[i] = dValue ;
dSum += dValue;
}
// 归一化
for(i=0; i
{
(*pdKernel)[i] /= dSum;
}
}
高斯滤波
/*************************************************************************
*
* \函数名称:
* GaussianSmooth()
*
* \输入参数:
* unsigned char * pUnchImg - 指向图象数据的指针
* int nWidth - 图象数据宽度
* int nHeight - 图象数据高度
* double dSigma - 高斯函数的标准差
* unsigned char * pUnchSmthdImg - 指向经过平滑之后的图象数据
*
* \返回值:
* 无
*
* \说明:
* 为了抑止噪声,采用高斯滤波对图象进行滤波,滤波先对x方向进行,然后对
* y方向进行。
*
*************************************************************************
*/
void GaussianSmooth(unsigned char *pUnchImg, int nWidth, int nHeight,
double sigma, unsigned char * pUnchSmthdImg)
{
// 循环控制变量
int y;
int x;
int i;
// 高斯滤波器的数组长度
int nWindowSize;
// 窗口长度的1/2
int nHalfLen;
// 一维高斯数据滤波器
double *pdKernel ;
// 高斯系数与图象数据的点乘
double dDotMul ;
// 高斯滤波系数的总和
double dWeightSum ;
// 中间变量
double * pdTmp ;
// 分配内存
pdTmp = new double[nWidth*nHeight];
// 产生一维高斯数据滤波器
// MakeGauss(sigma, &dKernel, &nWindowSize);
MakeGauss(sigma, &pdKernel, &nWindowSize) ;
// MakeGauss返回窗口的长度,利用此变量计算窗口的半长
nHalfLen = nWindowSize / 2;
// x方向进行滤波
for(y=0; y
{
for(x=0; x
{
dDotMul = 0;
dWeightSum = 0;
for(i=(-nHalfLen); i<=nHalfLen; i++)
{
// 判断是否在图象内部
if( (i+x) >= 0 && (i+x) < nWidth )
{
dDotMul += (double)pUnchImg[y*nWidth + (i+x)] * pdKernel[nHalfLen+i];
dWeightSum += pdKernel[nHalfLen+i];
}
}
pdTmp[y*nWidth + x] = dDotMul/dWeightSum ;
}
}
// y方向进行滤波
for(x=0; x
{
for(y=0; y
{
dDotMul = 0;
dWeightSum = 0;
for(i=(-nHalfLen); i<=nHalfLen; i++)
{
// 判断是否在图象内部
if( (i+y) >= 0 && (i+y) < nHeight )
{
dDotMul += (double)pdTmp[(y+i)*nWidth + x] * pdKernel[nHalfLen+i];
dWeightSum += pdKernel[nHalfLen+i];
}
}
pUnchSmthdImg[y*nWidth + x] = (unsigned char)(int)dDotMul/dWeightSum ;
}
}
// 释放内存
delete []pdKernel;
pdKernel = NULL ;
delete []pdTmp;
pdTmp = NULL;
}
void gaussianFilter(uchar* data,int width,int height)
02
{
03
int i, j, index, sum;
04
int templates[9] = { 1, 2, 1,
05
2, 4, 2,
06
1, 2, 1 };
07
sum = height * width *sizeof(uchar);
08
uchar *tmpdata = (uchar*)malloc(sum);
09
memcpy((char*)tmpdata,(char*)data, sum);
10
for(i = 1;i < height - 1;i++)
11
{
12
for(j = 1;j < width - 1;j++)
13
{
14
index = sum = 0;
15
for(int m = i - 1;m < i + 2;m++)
16
{
17
for(int n = j - 1; n < j + 2;n++)
18
{
19
sum +=
20
tmpdata[m * width + n] *
21
templates[index++];
22
}
23
}
24
data[i * width + j] = sum / 16;
25
}
26
}
27
free(tmpdata);
28
}
一个模板
//**********************************************************************
//模板操作
//图像信息头
//图像数据
//模板大小 以0开始
//模板中心元素 以0开始
//模板数据
//模板系数
//**********************************************************************
BOOL ImgTemplate(BITMAPINFO* pbmpinfo,BYTE* pbmpdata,CSize TemplateSize,CSize TemplateCertel ,int *template_box,float coef)
{
LONG imagewidth=pbmpinfo->bmiHeader.biWidth;
LONG imageheigth=pbmpinfo->bmiHeader.biHeight;
LONG i=0,j=0,k=0,heigth=0,width=0;
//data is not null
if (pbmpdata == NULL)
{
return FALSE;
}
//image size
if (imageheigth <= TemplateSize.cy || imagewidth <= TemplateSize.cx)
{
return FALSE;
}
if (TemplateCertel.cx < 0 || TemplateCertel.cy < 0 || TemplateCertel.cx > TemplateSize.cx || TemplateCertel.cy > TemplateSize.cy)
{
return FALSE;
}
//color must be gray
if (pbmpinfo->bmiHeader.biBitCount != 8)
{
AfxMessageBox("只对灰度图像进行操作!");
return FALSE;
}
//image size
LONG Linebyte =( pbmpinfo->bmiHeader.biBitCount * imagewidth +31)/32*4;
LONG ImageSize=Linebyte * imageheigth;
//分配空间
BYTE *pNewbmpdata=(BYTE*)malloc(ImageSize);
//copy data
if (pNewbmpdata == NULL)
{
return FALSE;
}
memcpy(pNewbmpdata,pbmpdata,ImageSize);
BYTE *psrc=NULL;
BYTE *pdest=NULL;
LONG result=0;
for (heigth = TemplateCertel.cy ; heigth < imageheigth - TemplateSize.cy + TemplateCertel.cy + 1 ;heigth++ )
{
for ( width = TemplateCertel.cx ; width < imagewidth - TemplateSize.cx + TemplateCertel.cx + 1 ; width++)
{
psrc = (unsigned char *)pbmpdata+(ImageSize-Linebyte-
heigth*Linebyte)+width;
pdest = (unsigned char *)pNewbmpdata+(ImageSize-Linebyte-
heigth*Linebyte)+width;
j=0;
result=0;
for ( i = - TemplateCertel.cy ; i
{
for (k = - TemplateCertel.cx ; k
{
result += (LONG)(*(psrc + i * Linebyte + k)) * template_box[j++];
}
}
result = (LONG)(result * coef);
if (result>255)
{
result=255;
}
if (result<0)
{
result=0;
}
*pdest=(unsigned char)result;
}
}
memcpy(pbmpdata,pNewbmpdata,ImageSize);
free(pNewbmpdata);
return TRUE;
}