?? 二值化.txt
字號:
我記得我那時主要處理灰度圖,灰度圖像素是從0~255的,假設120是分解,你可以將灰度值小于120的像素的灰度值置為0,將灰度值大于120的像素的灰度值置為1,這樣整個圖像就成了黑白兩色了。
二值化的難點不是編程,而是找閾值,120就是閾值
另外,“用C語言實現對圖像的二值化”是我覺得有些奇怪,C語言只是語法,它不是編程工具,你必須用vc或者bcb等工具編程才行
你的郵箱我發給你一些相關的閾值分割的論文。還有幾個全局閾值選取得源代碼,一個是迭代法,一個是大津法。局部閾值的比較復雜,我也在這方面找呢。
/***************************************************************************
* 函數名稱
* 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;
}
}
} avaScript:window。top。space-addItem(14,5077,0,0,1,1,0);
// 復制圖像
memcpy(lpDIBBits, lpNewDIBBits, lWidth * lHeight);
// 釋放內存
LocalUnlock(hNewDIBBits);
LocalFree(hNewDIBBits);
// 返回
return TRUE;
}
// 迭代法
BOOL WINAPI MeanThreshold(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; iIterationTimes < 100 && iThreshold != iNewThreshold; iIterationTimes++)
{
iThreshold = iNewThreshold;
lP1 = 0;
lS1 = 0;
lP2 = 0;
lS2 = 0;
// 求以iNewThresHold分割的兩個區域的灰度平均值
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++)
{
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;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -