大津法二值化的應用與實現

一、大津法二值化演算法

大津法是一種自適應閾值法,該演算法是由日本學者大津展之於1979年提出的,也被稱為OTSU演算法。

該演算法是對灰度圖像進行二值化的一種方法,它通過計算圖像的閾值,將圖像分成前景和背景兩部分。閾值能夠根據圖像的直方圖分布情況自適應的調整。

該演算法的主要思路如下:

1、對圖像的每一個灰度值進行統計,得到灰度直方圖。

2、遍歷灰度直方圖,計算每一個灰度值的「類內方差」。類內方差度量了同一區域內像素灰度分布的聚集程度,方差越小,表示像素值分布越聚集,對應的區域越容易被劃分為背景或者前景。

3、選取類內方差最小的灰度閾值作為二值化的閾值。

二、大津法二值化的代碼實現

接下來是一個C語言中實現大津法二值化的示例代碼:

// img -- 圖像數據
// w -- 圖像寬度
// h -- 圖像高度

int threshold = 0;
int pixelCount[256] = {0};
float pixelProb[256] = {0.0f};
float cumProb[256] = {0.0f};
float cumMean[256] = {0.0f};
float sigma[256] = {0.0f};

// 計算像素值出現的頻率
for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
        int pixel = img[i*w + j];
        pixelCount[pixel]++;
    }
}

// 計算像素值出現的概率
for (int i = 0; i < 256; i++) {
    pixelProb[i] = (float)pixelCount[i] / (float)(w * h);
}

// 計算累積概率和累積分布均值
for (int i = 0; i < 256; i++) {
    if (i == 0) {
        cumProb[i] = pixelProb[i];
        cumMean[i] = i * pixelProb[i];
    } else {
        cumProb[i] = cumProb[i-1] + pixelProb[i];
        cumMean[i] = cumMean[i-1] + i * pixelProb[i];
    }
}

// 計算全局平均值
float globalMean = cumMean[255];

// 計算類內方差
for (int i = 0; i < 256; i++) {
    if (i == 0 || cumProb[i] == 1.0f) {
        sigma[i] = 0.0f;
    } else {
        float weight = cumProb[i];
        float mean = cumMean[i] / cumProb[i];
        sigma[i] = (globalMean * weight - mean) * (globalMean * weight - mean) / (weight * (1.0f - weight));
    }
}

// 選取類內方差最小的像素值作為閾值
float maxSigma = 0.0f;
for (int i = 0; i  maxSigma) {
        maxSigma = sigma[i];
        threshold = i;
    }
}

// 對圖像進行二值化
for (int i = 0; i < h; i++) {
    for (int j = 0; j  threshold) {
            img[i*w + j] = 255;
        } else {
            img[i*w + j] = 0;
        }
    }
}

三、大津法二值化的程序實現

除了使用C語言實現大津法二值化之外,我們還可以使用其他的編程語言實現。下面是使用MATLAB實現大津法二值化的示例代碼:

% img -- 圖像數據

histogram = imhist(img);
pixelProb = histogram / sum(histogram);

cumProb = cumsum(pixelProb);
cumMean = cumsum((0:255)'.*pixelProb);

globalMean = cumMean(end);

sigma = (globalMean*cumProb - cumMean).^2 ./ (cumProb.*(1-cumProb));

[~, threshold] = max(sigma);

bwImg = imbinarize(img, threshold/255); 

使用MATLAB時,可以使用imhist函數計算圖像的直方圖,使用imbinarize函數進行二值化。

四、大津法二值化後如何知道具體閾值

大津法二值化得到的閾值可以用於對圖像進行二值化處理。

我們可以在處理圖像的時候,將得到的閾值作為參數傳入二值化函數。在C語言中,可以使用以下代碼進行二值化:

int threshold = 128;
// img -- 圖像數據
// w -- 圖像寬度
// h -- 圖像高度

for (int i = 0; i < h; i++) {
    for (int j = 0; j  threshold) {
            img[i*w + j] = 255;
        } else {
            img[i*w + j] = 0;
        }
    }
}

在MATLAB中,可以使用以下代碼進行二值化:

bwImg = imbinarize(img, threshold/255); 

五、大津演算法求二值化閾值選取

大津演算法求二值化閾值選取是對大津法二值化的改進,該演算法通過迭代的方式求出最優的閾值,從而使得閾值更加準確。

該演算法主要思路如下:

1、初始化閾值T為圖像的平均值。

2、將像素分為兩類:小於等於閾值T和大於閾值T。

3、計算兩個類的平均值:μ1和μ2。

4、計算兩個類對應的類內方差:var1和var2。

5、計算全局類內方差:intraVariance。

6、將閾值T更新為使得全局類內方差最小的值。

7、重複步驟2~6,直到閾值T的變化小於給定的閾值。

下面是使用C語言實現大津演算法求二值化閾值選取的示例代碼:

// img -- 圖像數據
// w -- 圖像寬度
// h -- 圖像高度

#define THRESHOLD_DELTA 0.5f

float threshold = 0.0f;

while (true) {

    int pixelCount1 = 0;
    int pixelCount2 = 0;
    float pixelProb1 = 0.0f;
    float pixelProb2 = 0.0f;
    float cumProb1 = 0.0f;
    float cumProb2 = 0.0f;
    float cumMean1 = 0.0f;
    float cumMean2 = 0.0f;
    float intraVariance = 0.0f;

    // 遍歷圖像,計算各種參數
    for (int i = 0; i < h; i++) {
        for (int j = 0; j  threshold) {
                pixelCount1++;
                cumMean1 += pixel;
            } else {
                pixelCount2++;
                cumMean2 += pixel;
            }
        }
    }

    pixelProb1 = (float)pixelCount1 / (float)(w * h);
    pixelProb2 = (float)pixelCount2 / (float)(w * h);
    cumProb1 = pixelProb1;
    cumProb2 = pixelProb2;
    cumMean1 /= pixelCount1;
    cumMean2 /= pixelCount2;

    // 計算類內方差和全局方差
    for (int i = 0; i < h; i++) {
        for (int j = 0; j  threshold) {
                intraVariance += (pixel-cumMean1)*(pixel-cumMean1);
            } else {
                intraVariance += (pixel-cumMean2)*(pixel-cumMean2);
            }
        }
    }

    intraVariance /= (float)(w*h);

    // 更新閾值
    float newThreshold = (cumMean1+cumMean2) / 2.0f;
    if (fabs(newThreshold-threshold) < THRESHOLD_DELTA) {
        threshold = newThreshold;
        break;
    }
    threshold = newThreshold;
}

// 對圖像進行二值化
for (int i = 0; i < h; i++) {
    for (int j = 0; j  threshold) {
            img[i*w + j] = 255;
        } else {
            img[i*w + j] = 0;
        }
    }
}

上述代碼首先定義了一個閾值的變化閾值,當兩次迭代之間的閾值變化小於該值時,演算法停止。接下來進行迭代,直到達到停止條件。在每一次迭代過程中,首先將圖像分為兩類,統計每一類的像素值頻率和像素值分布情況等參數,然後計算全局類內方差,更新閾值。最後,使用更新後的閾值對圖像進行二值化處理。

原創文章,作者:EPXP,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/142125.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
EPXP的頭像EPXP
上一篇 2024-10-10 08:47
下一篇 2024-10-10 08:47

發表回復

登錄後才能評論