您的位置:首页 > 编程语言 > C语言/C++

VC++高斯滤波\中值滤波实现图像模糊处理

2015-02-14 16:18 381 查看

一、算法

高斯模糊算法 详见:高斯模糊,基本思想就是利用高斯函数,将一个坐标点的所有邻域的加权平均值设置为这些点的颜色值。

中值滤波算法就更简单了:将一个坐标点的所有邻域的平均值设置为这些点的像素值。

二、算法的代码实现

高斯函数:


使用宏定义来替换:

#define PI<span style="white-space:pre">	</span>3.1415926
//高斯模糊函数
#define GAUSS_FUN(x, y) (exp(-(x*x)/(double)(2*y*y)))/(sqrt(2.0*PI)*y)
#define SQUARE(x)<span style="white-space:pre">	</span>((x)*(x))

//暂且定义sigma为10
const double sigma=10;


高斯模糊算法处理像素

//高斯模糊,nRadius为平均取值的半径,半径越大,图像越模糊,处理时间也越长
bool GaussFilter( DWORD* pData, DWORD* pCopy, const int nWidth, const int nHeight, const int nRadius/*=1*/ )
{
if ( nWidth<=0 || nHeight<=0 || nRadius<=0 )
return false;
for ( int ny=0; ny<nHeight; ++ny )
{
for ( int nx=0; nx<nWidth; ++nx )
{
vector<COLOR_DATA> cdList;
cdList.reserve(200);
COLOR_DATA cd;
double dTotal=0;
for ( int m=nx-nRadius; m<=nx+nRadius; ++m )
{
if ( m<0 || m>=nWidth ) continue;
for ( int n=ny-nRadius; n<=ny+nRadius; ++n )
{
if ( n<0 || n>=nHeight ) continue;
cd.dDistance=GAUSS_FUN(sqrt((double)(SQUARE(m-nx)+SQUARE(n-ny))), sigma);
dTotal+=cd.dDistance;
cd.dwColor=*(pData+n*nWidth+m);
cdList.push_back(cd);
}
}
if ( cdList.size()>0 )
{//这里来计算整个邻域内所有像素点的加权平均值
std::vector<COLOR_DATA>::const_iterator itor=cdList.begin();
double r=0, g=0, b=0;
for ( ; itor!=cdList.end(); ++itor )
{
double dRate=itor->dDistance/dTotal;//距离中心点越远,权值越小
r+=GetRValue(itor->dwColor)*dRate;
g+=GetGValue(itor->dwColor)*dRate;
b+=GetBValue(itor->dwColor)*dRate;
}
*(pCopy+ny*nWidth+nx)=RGB((int)r, (int)g, (int)b);
}
}
}
return true;
}
中值滤波函数就很简单了,不细说

//中值滤波
bool MedianFilter( DWORD* pData, DWORD* pCopy, const int nWidth, const int nHeight, const int nRadius )
{
if ( nWidth<=0 || nHeight<=0 || nRadius<=0 )
return false;
for ( int ny=0; ny<nHeight; ++ny )
{
for ( int nx=0; nx<nWidth; ++nx )
{//扫描每一个点的邻域,把他们的像素值保存起来。
vector<DWORD> data;
for ( int m=nx-nRadius; m<=nx+nRadius; ++m )
{
if ( m<0 || m>=nWidth || (m==nx) ) continue;
for ( int n=ny-nRadius; n<=ny+nRadius; ++n )
{
if ( n<0 || n>=nHeight || (n==ny) ) continue;
data.push_back(*(pData+n*nWidth+m));
}
}
if ( data.size()>0 )
{
std::sort(data.begin(), data.end());//排序
*(pCopy+ny*nWidth+nx)=data[data.size()/2];//取所有像素值的中值作为整个区域的像素值
}
}
}
return true;
}


线程函数中处理图像的像素,完成后发消息通知界面更新

DWORD __stdcall GaussThread(LPVOID lpParam)
{
HLOCAL hMem=LocalAlloc(LHND, g_lBmpSize);
DWORD* pBuffer=(DWORD*)LocalLock(hMem);
LONG lCopySize=::GetBitmapBits(g_hBitmap1, g_lBmpSize, pBuffer);
HLOCAL hMemCopy=LocalAlloc(LHND, g_lBmpSize);
DWORD* pBufferCopy=(DWORD*)LocalLock(hMemCopy);
//MedianFilter(pBuffer, bmMetric.bmWidth, bmMetric.bmHeight, 1);
//MedianFilter(pBuffer, pBufferCopy, g_nBmpWidth, g_nBmpHeight, 3);
//MedianFilterRGB(pBuffer, pBufferCopy, g_nBmpWidth, g_nBmpHeight, 10);
GaussFilter(pBuffer, pBufferCopy, g_nBmpWidth, g_nBmpHeight, 6);
::SetBitmapBits(g_hBitmap1, g_lBmpSize, pBufferCopy);
LocalUnlock(hMem);
LocalFree(hMem);
LocalUnlock(hMemCopy);
LocalFree(hMemCopy);
::PostMessage(g_hMainWnd, WM_GAUSS_MSG, 0, 0);
return 0;
}


三、程序运行效果图:

邻域距离为6时的高斯模糊处理效果:



邻域距离为12时的高斯模糊处理效果:



邻域距离为24时的高斯模糊处理效果:



这时候,线程处理得花好几十秒时间了。

接着,对比中值滤波处理效果,邻域距离为6、12、24时的三张效果图分别为:







四、后记

对比效果图可以看出,高斯滤波模糊效果比较平滑,中值滤波则比较粗糙。当然了,高斯算法相对负责,其处理时也很花费的时间。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: