前几天,应一个网友的要求,根据文章《图像的自适应模糊阈值分割法》,写了个简单的代码:
/*
名称:BlurCure
参数:lpBmp - 图像数据指针
lSrcWidth - 图像宽度
lSrcHeight - 图像高度
dLineBites - 图像单行数据量
说明:获取模糊阈值分割的模糊曲线dBlurData
*/
void BlurCurve(LPSTR lpBmp, long lSrcWidth, long lSrcHeight, DWORD dLineBites)
{
if(lpBmp == NULL)
return;
int i,j;
LPSTR lpSrcPtr = NULL;
BYTE btTempValue = 0;
int nTistogram[256] = {0};
for (i = 0;i < lSrcHeight; ++i)
{
lpSrcPtr = lpBmp + i * dLineBites;
for (j = 0;j <lSrcWidth; ++j)
{
btTempValue = (BYTE)*(lpSrcPtr + j);
nTistogram[btTempValue]++;
}
}
int nWinWidth = 20;//搜索的窗宽
double dBlurData[256]={0};
double dGetMemship = 0;
for (int nGrayPos = 0; nGrayPos < 256; ++nGrayPos)
{
for (j = 0;j <256; ++j)
{
dGetMemship = MemshipFunc(j,nGrayPos,nWinWidth);
if(dGetMemship > 0.5)
dGetMemship = 1 - dGetMemship;
if(dGetMemship < 0)
dGetMemship = 0;
dBlurData[nGrayPos] += nTistogram[j]*dGetMemship;
}
dBlurData[nGrayPos] *= 2.0/(lSrcHeight*lSrcWidth);
}
}
/*
隶属度函数:MemshipFunc
*/
double MemshipFunc(int nGray,const int& nWinCent,const int& nWinWidth)
{
int nLeft = nWinCent-nWinWidth;
int nRight = nWinCent+nWinWidth;
if(nGray >= 0 && nGray <= nLeft)
return 0;
else if(nGray > nLeft && nGray <= nWinCent)
{
double dMem = double(nGray - nLeft)/(2*nWinWidth);
return 2*dMem*dMem;
}
else if(nGray > nWinCent && nGray <= nRight)
{
double dMem = double(nGray - nLeft)/(2*nWinWidth);
return 1-2*dMem*dMem;
}
return 1;
}
原始图像:
直方图:
模糊曲线:
从上图可以看出,经过模糊化后,直方图变的平滑了很多,下一步主要进行曲线最小值的搜索。
另外,模糊缺陷的保值性与窗宽nWinWidth 有很大的关系,窗宽取的合适,获得的模糊曲线就更容易分割。而所谓自适应模糊化分割,就是找到合适的nWinWdith,目前,找合适的nWinWdith有很多方法,大部分都是搜索法,然后按照设定的准则停止(比如文中讲到的极点法、还有区间法等)搜索,最后获得合适的nWinWidth。
我将再后续的工作中,尝试不同的搜索方法,并把代码奉上。