高斯模糊算法的设计与实现 GaussianBlur

算法部分,我参考了这篇博客 http://blog.csdn.net/maozefa/article/details/5576499
namespace GaussianBlur{
#define PI 3.14156
	double * dArray = NULL;
	double dQ = 0;
	int iRadius = 0;

	void InitGaussianBlur(double Q , int R)
	{
		dQ = Q;
		iRadius = R;

		dArray = new double[2*iRadius + 1];

		double x;
		for (int i = -iRadius ; i <= iRadius ; ++i)
		{
			assert(dQ!=0);
			x = i/dQ;
			dArray[i+iRadius] = exp((double)(-x*x/2));
		}

		double dUniform = 0;
		for (int i = -iRadius ; i <= iRadius ; ++i)
		{
			dUniform += dArray[i+iRadius];
		}

		if (dUniform != 1)
		{
			for (int i = -iRadius ; i <= iRadius ; ++i)
			{
				dArray[i+iRadius] /= dUniform;
			}

		}
	}

	double GetFactor(int i)
	{
		if (dArray)
		{
			if (i>=0 && i<2*iRadius+1)
			{
				return dArray[i];
			}
		}

		return 0;
	}

	void UnInitGaussianBlur()
	{
		if (dArray)
		{
			delete []dArray;
			dArray = NULL;
		}
	}
}

上面这段代码是用于生成一个向量的函数。高斯模糊有两种方法,一种是用二元函数,就是在空间上正态分布的二元函数,或者使用一元函数,此时只能在图像的每一行上进行使用。高斯模糊的两个函数 http://www.cnblogs.com/hoodlum1980/articles/1088567.html

HBITMAP GaussianBlurFunc(HDC hDC, int x, int y, int iWidth, int iHeight )
{
	//定义图形大小
	int iPixel = 24;
	int iBytesPerPixel = iPixel/8;

	//图形格式参数
	LPBITMAPINFO lpbmih = new BITMAPINFO;
	lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	lpbmih->bmiHeader.biWidth = iWidth;
	lpbmih->bmiHeader.biHeight = iHeight;
	lpbmih->bmiHeader.biPlanes = 1;
	lpbmih->bmiHeader.biBitCount = iPixel;
	lpbmih->bmiHeader.biCompression = BI_RGB;
	lpbmih->bmiHeader.biSizeImage = 0;
	lpbmih->bmiHeader.biXPelsPerMeter = 0;
	lpbmih->bmiHeader.biYPelsPerMeter = 0;
	lpbmih->bmiHeader.biClrUsed = 0;
	lpbmih->bmiHeader.biClrImportant = 0;

	//创建位图数据
	BYTE *pBits;

	HDC hdcMem = CreateCompatibleDC(hDC);
	HBITMAP hBitMap = CreateDIBSection(hdcMem,lpbmih,DIB_RGB_COLORS,(void **)&pBits,NULL,0);

	HGDIOBJ hOld = SelectObject( hdcMem, hBitMap);

	::BitBlt( hdcMem, 0, 0, iWidth, iHeight, hDC, x, y, SRCCOPY);

	BYTE * pBitsCurrent;
	BYTE * newBitmap;
	BYTE r,g,b;
	BYTE newR,newG,newB;

	int iBytesScanLine;

	iBytesScanLine = ((iBytesPerPixel * iWidth + 3)>>2)<<2;

	newBitmap = new BYTE[iBytesScanLine*iHeight];
	memset(newBitmap , 0 , iBytesScanLine*iHeight);
	BYTE * newBitmapCurrentPointer = newBitmap;

	double Q = 3;
	int R = 5;

	GaussianBlur::InitGaussianBlur(Q , R);

	BYTE * processBegin , * processEnd , * processCurrent;
	int indexBegin , indexEnd , indexCurrent;
	for (int j=0;j<iHeight;++j)
	{
		for (int i=0;i<iWidth;++i)
		{
			pBitsCurrent = pBits + j * iBytesScanLine + i * 3;
			newBitmapCurrentPointer = newBitmap + j * iBytesScanLine + i * 3;

			b = pBitsCurrent[0];
			g = pBitsCurrent[1];
			r = pBitsCurrent[2];

			if (i < R)
			{
				processBegin = pBits + j * iBytesScanLine;
				indexBegin = R - i;
			}
			else
			{
				processBegin = pBitsCurrent - iBytesPerPixel * R;
				indexBegin = 0;
			}

			if (i > iWidth - R - 1)
			{
				processEnd = pBitsCurrent + j * iBytesScanLine + iWidth * 3;
				indexEnd = R - i + iWidth - 1;
			}
			else
			{
				processEnd = pBitsCurrent + R * iBytesPerPixel;
				indexEnd = 2 * R;
			}
			
			processCurrent = processBegin,indexCurrent = indexBegin ;
			newB = 0 , newG = 0 , newR = 0;
			for (; processCurrent <= processEnd && indexCurrent <= indexEnd ; processCurrent += iBytesPerPixel , indexCurrent += 1)
			{
				newB += processCurrent[0] * GaussianBlur::GetFactor(indexCurrent);
				newG += processCurrent[1] * GaussianBlur::GetFactor(indexCurrent);
				newR += processCurrent[2] * GaussianBlur::GetFactor(indexCurrent);
			}

			newBitmapCurrentPointer[0] = newB;
			newBitmapCurrentPointer[1] = newG;
			newBitmapCurrentPointer[2] = newR;
		}
	}

#ifndef USE_TWO_GAUSSIANBLUR
	memcpy(pBits , newBitmap , iBytesScanLine*iHeight);
	delete [] newBitmap;
#else

	for (int j=0;j<iHeight;++j)
	{
		for (int i=0;i<iWidth;++i)
		{
			pBitsCurrent = pBits + j * iBytesScanLine + i * 3;
			newBitmapCurrentPointer = newBitmap + j * iBytesScanLine + i * 3;

			b = newBitmapCurrentPointer[0];
			g = newBitmapCurrentPointer[1];
			r = newBitmapCurrentPointer[2];

			if (j < R)
			{
				processBegin = pBits + i * 3;
				indexBegin = R - j;
			}
			else
			{
				processBegin = pBitsCurrent - iBytesScanLine * R;
				indexBegin = 0;
			}

			if (j > iWidth - R - 1)
			{
				processEnd = pBitsCurrent + iHeight * iBytesScanLine + i * 3;
				indexEnd = R - j + iHeight - 1;
			}
			else
			{
				processEnd = pBitsCurrent + R * iBytesScanLine;
				indexEnd = 2 * R;
			}

			processCurrent = processBegin,indexCurrent = indexBegin ;
			newB = 0 , newG = 0 , newR = 0;
			for (; processCurrent <= processEnd && indexCurrent <= indexEnd ; processCurrent += iBytesScanLine , indexCurrent += 1)
			{
				newB += newBitmapCurrentPointer[0] * GaussianBlur::GetFactor(indexCurrent);
				newG += newBitmapCurrentPointer[1] * GaussianBlur::GetFactor(indexCurrent);
				newR += newBitmapCurrentPointer[2] * GaussianBlur::GetFactor(indexCurrent);
			}

			pBitsCurrent[0] = newB;
			pBitsCurrent[1] = newG;
			pBitsCurrent[2] = newR;
		}
	}

	delete []newBitmap;
#endif



	SelectObject(hdcMem, hOld);
	DeleteObject(hdcMem);

	GaussianBlur::UnInitGaussianBlur();

	return hBitMap;
}
如果没有定义USE_TWO_GAUSSIANBLUR宏,那么图像处理一次,否则处理两次,也就是在行上处理一次,列上处理一次。

高斯模糊本质上是利用周边的点对中心的点进行模糊,比如有一个点,这个点受到周围像素值的混合,使这个点受到影响,而且越远的点对该点的影响会较小,之所以选择正态分布的函数,原因很简单,就是权值之和为1,并且中间位置占的比重最大,越往边上,值会越小。

举个例子。

这一行有一系列的点,A0,A1,A2,A3,A4。A2点受到周围两个点的影响,A2 = 较大权值*A2 + 较小权值*(A1 + A3) + 最小权值 *(A0+A4),这个权值可以怎么来呢, 就用一元的正态分布的函数,这几个权值肯定达不到1,因为正态分布的积分值才是1,所以要对其进行放大为1。

下面是Q=3,R=5处理后的效果图

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值