關於二值化函數cvAdaptiveThreshold和cvThreshold以及OSTU

(1)函數cvAdaptiveThreshold的確可以將灰度圖像二值化,但它的主要功能應該是邊緣提取,並且參數param1主要是用來控制邊緣的類型和粗細的,這些在軟件自帶的參考手冊中均未提及。雖然手冊裏的閾值計算和判斷方法與代碼是一致的,但其函數功能說明卻給人一種通常意義上的“圖像二值化”的印象。

(2)有趣的是,我也留意了一下資料介紹的固定閾值化函數cvThreshold,其實它也有一種自適應閾值方法,那就是OSTU(大津法)!!只需要設定參數thresh_type的值爲CV_THRESH_OTSU即可。

(3)前面分析得沒問題,自適應二值化就是這樣的。這是一種高效實現。自適應二值化計算像素的鄰域的平均灰度,來決定二值化的值。如果整個區域幾乎是一樣灰度的,則無法給出合適的結果了。之所以看起來像邊緣檢測,是因爲窗尺寸設置的小,可以改大一點試一試。
cvAdaptiveThreshold( src, dst, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 21); //窗設置爲21
沒有萬能的二值化方法,具體問題具體分析,自適應二值化對於光照不均的文字,條碼等,效果很好。窗口大小選擇,考慮被檢測物體尺寸。

(4)附:

/*======================================================================*/
/* OTSU global thresholding routine */
/*======================================================================*/

void otsu (IplImage *image)
{
int w = image->width;
int h = image->height;

unsigned char *np; // 圖像指針
unsigned char pixel;
int thresholdValue=1; // 閾值
int ihist[256]; // 圖像直方圖,256個點

int i, j, k; // various counters
int n, n1, n2, gmin, gmax;
double m1, m2, sum, csum, fmax, sb;

// 對直方圖置零...
memset(ihist, 0, sizeof(ihist));

gmin=255; gmax=0;
// 生成直方圖
for (i = 0; i < h; i++) 
{
np = (unsigned char*)(image->imageData + image->widthStep*i);
for (j = 0; j < w; j++) 
{
pixel = np[j];
ihist[ pixel]++;
if(pixel > gmax) gmax= pixel;
if(pixel < gmin) gmin= pixel;
}
}

// set up everything
sum = csum = 0.0;
n = 0;

for (k = 0; k <= 255; k++) 
{
sum += k * ihist[k]; /* x*f(x) 質量矩*/
n += ihist[k]; /* f(x) 質量 */
}

if (!n) 
{
// if n has no value, there is problems...
//fprintf (stderr, "NOT NORMAL thresholdValue = 160\n");
thresholdValue = 160;
goto L;
}

// do the otsu global thresholding method
fmax = -1.0;
n1 = 0;
for (k = 0; k < 255; k++) 
{
n1 += ihist[k];
if (!n1) { continue; }
n2 = n - n1;
if (n2 == 0) { break; }
csum += k *ihist[k];
m1 = csum / n1;
m2 = (sum - csum) / n2;
sb = n1 * n2 *(m1 - m2) * (m1 - m2);
/* bbg: note: can be optimized. */
if (sb > fmax)
{
fmax = sb;
thresholdValue = k;
}
}

L:
for (i = 0; i < h; i++) 
{
np = (unsigned char*)(image->imageData + image->widthStep*i);
for (j = 0; j < w; j++) 
{
if(np[j] >= thresholdValue)
np[j] = 255;
else np[j] = 0;
}
}
}


 

發佈了70 篇原創文章 · 獲贊 18 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章