二值化是一个相当复杂的理论问题,如果不给出具体的应用要求是无法做的.
最简单的:
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;
}
///////////////////////////////////////////////////////////////
评论