http://blog.youkuaiyun.com/hejianhua/archive/2009/03/11/3979853.aspx
二值化是一个相当复杂的理论问题,如果不给出具体的应用要求是无法做的.
最简单的:
for(......)
if(PixelY[i,j]>T)
PixelY[i,j] = 255;
else
PixelY[i,j] = 0;
如果考虑具体问题,二值化算法不下100种.
/***************************************************************************
* 函数名称
* OSTUThreshold()
* 参数
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(像素数)
* LONG lHeight - 源图像高度(像素数)
* 返回值
* BOOL - 运算成功 返回TRUE , 否则 返回FALSE。
* 说明
* 该函数采用大津法进行阈值分割 二值化
***************************************************************************/
BOOL WINAPI OSTUThreshold(LPSTR lpDIBBits, LONG lWidth, LONG lHeight)
{
// 指向源图像像素指针
LPSTR lpSrc;
// 指向缓存图像指针
LPSTR lpDst;
// 指向缓存图像像素指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
// 循环变量
int i, j, t;
// 用于计算两个区域的中间变量
long lP1, lS1, lP2, lS2;
// 像素值
unsigned char pixel;
// 灰度直方图数组
long lHistogram[256];
// 阈值, 最大灰度值和最小灰度值, 两个区域的平均灰度值
unsigned char iThreshold, iNewThreshold, iMaxGrayValue, iMinGrayValue, iMean1GrayValue, iMean2GrayValue;
// 前景点数占图像比例, 背景点数占图像比例
double w0,w1;
// 方差
double G, tempG;
// 图像每行占字节数
LONG lLineBytes;
// 暂时分配内存, 以保存新图像
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
//分配内存失败
return FALSE;
}
// 锁定内存
lpNewDIBBits = (char *) LocalLock(hNewDIBBits);
// 初始化新分配的内存, 设定初始值为255
lpDst = (char *) lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
lLineBytes = WIDTHBYTES(lWidth * 8);
for(i= 0; i < 256; i++)
{
lHistogram[i] = 0;
}
// 获得灰度直方图,灰度最大值和灰度最小值
iMaxGrayValue = 0;
iMinGrayValue = 255;
for(i = 0; i < lWidth; i++)
{
for(j = 0; j < lHeight; j++)
{
lpSrc = (char *) lpDIBBits + lLineBytes * j + i;
pixel = (unsigned char) *lpSrc;
lHistogram[pixel]++;
// 修改最大灰度值和最小灰度值
if (iMinGrayValue > pixel)
{
iMinGrayValue = pixel;
}
if (iMaxGrayValue < pixel)
{
iMaxGrayValue = pixel;
}
}
}
// 遍历t, 选取最佳阈值
for(t = iMinGrayValue; t < iMaxGrayValue ; t++)
{
iNewThreshold = t;
lP1 = 0;
lS1 = 0;
lP2 = 0;
lS2 = 0;
// 求前景,背景两个区域的平均灰度值, 点数所占比例
for(i = iMinGrayValue; i <= iNewThreshold; i++)
{
lP1 += lHistogram[i] * i;
lS1 += lHistogram[i];
}
iMean1GrayValue = (unsigned char) (lP1/lS1);
w0 = (double) (lS1) / (lWidth * lHeight);
for(i = iNewThreshold + 1; i <= iMaxGrayValue; i++)
{
lP2 += lHistogram[i] * i;
lS2 += lHistogram[i];
}
iMean2GrayValue = (unsigned char) (lP2/lS2);
w1 = 1 - w0;
// 计算类间方差
G = (double) w0 * w1
* (iMean1GrayValue - iMean2GrayValue) * (iMean1GrayValue - iMean2GrayValue);
if (G > tempG)
{
tempG = G;
iThreshold = iNewThreshold;
}
}
// 根据阈值将图像二值化
for(i = 0; i < lWidth; i++)
{
for(j = 0; j < lHeight; j++)
{
lpSrc = (char *) lpDIBBits + lLineBytes * j + i;
lpDst = (char *) lpNewDIBBits + lLineBytes * j + i;
pixel = (unsigned char) *lpSrc;
if (pixel <= iThreshold)
{
*lpDst = (unsigned char)0;
}
else
{
*lpDst = (unsigned char) 255;
}
}
}
// 复制图像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 释放内存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
*
* 函数名称:
* ThresholdDIB()
*
* 参数:
* LPSTR lpDIBBits - 指向源DIB图像指针
* LONG lWidth - 源图像宽度(象素数)
* LONG lHeight - 源图像高度(象素数)
*
* 返回值:
* BOOL - 运算成功返回TRUE,否则返回FALSE。
*
* 说明:
* 该函数用 迭代法 对图像进行阈值分割运算。
*
************************************************************************/
{
// 指向源图像的指针
LPSTR lpSrc;
// 指向缓存图像的指针
LPSTR lpDst;
// 指向缓存DIB图像的指针
LPSTR lpNewDIBBits;
HLOCAL hNewDIBBits;
long i;
long j;
unsigned char pixel;
long lHistogram[256];
unsigned char iThreshold,iNewThreshold,iMaxGrayValue,iMinGrayValue,iMean1GrayValue,iMean2GrayValue;
long lP1,lP2,lS1,lS2;
int iIterationTimes;
LONG lLineBytes;
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
{
// 分配内存失败
return FALSE;
}
// 锁定内存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
lLineBytes = WIDTHBYTES(lWidth * 8);
{
lHistogram[i]=0;
}
iMaxGrayValue = 0;
iMinGrayValue = 255;
for (i = 0;i < lWidth ;i++)
{
for(j = 0;j < lHeight ;j++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
pixel = (unsigned char)*lpSrc;
lHistogram[pixel]++;
//修改最大,最小灰度值
if(iMinGrayValue > pixel)
{
iMinGrayValue = pixel;
}
if(iMaxGrayValue < pixel)
{
iMaxGrayValue = pixel;
}
}
}
iNewThreshold = (iMinGrayValue + iMaxGrayValue)/2;
iThreshold = 0;
for(iIterationTimes = 0; iThreshold != iNewThreshold && iIterationTimes < 100;iIterationTimes ++)
{
iThreshold = iNewThreshold;
lP1 =0;
lP2 =0;
lS1 = 0;
lS2 = 0;
//求两个区域的灰度平均值
for (i = iMinGrayValue;i < iThreshold;i++)
{
lP1 += lHistogram[i]*i;
lS1 += lHistogram[i];
}
iMean1GrayValue = (unsigned char)(lP1 / lS1);
for (i = iThreshold+1;i < iMaxGrayValue;i++)
{
lP2 += lHistogram[i]*i;
lS2 += lHistogram[i];
}
iMean2GrayValue = (unsigned char)(lP2 / lS2);
iNewThreshold = (iMean1GrayValue + iMean2GrayValue)/2;
}
for (i = 0;i < lWidth ;i++)
{
for(j = 0;j < lHeight ;j++)
{
// 指向源图像倒数第j行,第i个象素的指针
lpSrc = (char *)lpDIBBits + lLineBytes * j + i;
// 指向目标图像倒数第j行,第i个象素的指针
lpDst = (char *)lpNewDIBBits + lLineBytes * j + i;
if(pixel <= iThreshold)
{
*lpDst = (unsigned char)0;
}
else
{
*lpDst = (unsigned char)255;
}
}
}
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return TRUE;
}
///