/*************************************************************************
*
* 函數名稱:
* ThresholdDIB()
*
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
*
* 返回值:
* BOOL - 運算成功返回TRUE,不然返回FALSE。
*
* 說明:
* 該函數用於對圖像進行閾值分割運算:二值化
*
************************************************************************/
BOOL
WINAPI ThresholdDIB(
LPSTR
lpDIBBits,
LONG
lWidth,
LONG
lHeight)
{
// 指向源圖像的指針
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);
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++)
{
// 指向源圖像倒數第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;
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;
}