一、大津法二值化演算法
大津法是一種自適應閾值法,該演算法是由日本學者大津展之於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