一、大津法二值化算法
大津法是一種自適應閾值法,該算法是由日本學者大津展之於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-hant/n/142125.html
微信掃一掃
支付寶掃一掃