Ⅰ 如何用C語言實現對圖像的二值化
/*************************************************************************
* 該函數用於對圖像進行閾值分割運算
* 參數:
* LPSTR lpDIBBits - 指向源DIB圖像指針
* LONG lWidth - 源圖像寬度(象素數)
* LONG lHeight - 源圖像高度(象素數)
************************************************************************/
BOOL ImageChangeProc::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 Threshold,NewThreshold,MaxGrayValue,MinGrayValue,Temp1GrayValue,Temp2GrayValue;
//用於計算區域灰度平均值的中間變數
long lP1,lP2,lS1,lS2;
//迭代次數
int IterationTimes;
LONG lLineBytes;
hNewDIBBits = LocalAlloc(LHND, lWidth * lHeight);
if (hNewDIBBits == NULL)
{
// 分配內存失敗
return FALSE;
}
// 鎖定內存
lpNewDIBBits = (char * )LocalLock(hNewDIBBits);
// 初始化新分配的內存
lpDst = (char *)lpNewDIBBits;
memset(lpDst, (BYTE)255, lWidth * lHeight);
lLineBytes = WIDTHBYTES(lWidth * 8);
for (i = 0; i < 256;i++)
{
lHistogram[i]=0;
}
//獲得直方圖
MaxGrayValue = 0;
MinGrayValue = 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(MinGrayValue > pixel)
{
MinGrayValue = pixel;
}
if(MaxGrayValue < pixel)
{
MaxGrayValue = pixel;
}
}
}
//迭代求最佳閾值
NewThreshold = (MinGrayValue + MaxGrayValue)/2;
Threshold = 0;
for(IterationTimes = 0; Threshold != NewThreshold && IterationTimes < 1000;IterationTimes ++)
{
Threshold = NewThreshold;
lP1 =0;
lP2 =0;
lS1 = 0;
lS2 = 0;
//求兩個區域的灰度平均值
for (i = MinGrayValue;i <=Threshold;i++)
{
lP1 += lHistogram[i]*i;
lS1 += lHistogram[i];
}
for (i = Threshold+1;i<MaxGrayValue;i++)
{
lP2 += lHistogram[i]*i;
lS2 += lHistogram[i];
}
if(lS1==0||lS2==0)
{
// 釋放內存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
return FALSE;
}
Temp1GrayValue = (unsigned char)(lP1 / lS1);
Temp2GrayValue = (unsigned char)(lP2 / lS2);
NewThreshold = (Temp1GrayValue + Temp2GrayValue)/2;
}
//根據閾值將圖像二值化
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 <= Threshold)
{
*lpDst = (unsigned char)0;
}
else
{
*lpDst = (unsigned char)255;
}
}
}
// 復制圖像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 釋放內存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
參考:http://topic.csdn.net/t/20030909/13/2240079.html