Wellner 1993快速自適應的圖像二值化方法的提高 (Derek Bradley and Gerhard Roth 2007)
前面一種方案實際上還是存在一定的問題的, 就是這個避重就輕的初始g(n)值127*s(127表示0-255之間的中間值), 這個東西帶來的最直接的問題就是邊緣的效果在這個算法下是不咋地的。 其實從這個所謂的"Wellner 1993", 後人又做了很多的改進, 使之效率更高, 效果更好。比方說這個Derek Bradley和Gerhard Roth搞的這個所謂 Adaptive Thresholding Using the Integral Image 在這個網頁
http://www.scs.carleton.ca/~roth/iit-publications-iti/docs/gerh-50002.pdf 可以看到一些他的蹤跡。
這個算法的基本思想是這樣的,為了打破原來算法的初始值問題以及掃描順序的問題, 這裡的像素二值化的時候, 直接使用周圍矩形像素的顏色作比較,這樣來判斷像素值更科學。我們對算法的介紹從求和面積表(Summed-Area Table)開始. 這個求和面積表簡單點說就是維護一張表, 表中的元素值就是它左上位置的所有像素的像素值和。(數學公式在這裡編輯簡直是噩夢!只能放圖了無圖無真相:))
左邊就是原始像素值, 右邊的就是累加得到的表,
比方說這個表裡面的(2,2)位置的8就是通過2+3+3+0得到的,
又例如:(3, 3) 的16 = 2 + 3 + 2 + 3 + 0 + 1+ 1 + 3 + 1
而這個最大值28就是所有像素的累加和。得到這個和和我們的二值化有什麼關聯呢?前面我們提到了在新的這個算法裡面像素的值以來於周圍像素的顏色, 那周圍像素的顏色如何表示呢? 我們可以通過這個表輕松獲得, 且看下面一張圖:
這裡的UL, LL, UR, LR表示的就是前面這個求和表裡面的值, 如果我們要判斷綠色區域中這個+號位置的值, 我們就要計算整個綠色區域的平均像素值, 如何計算呢? 有了新的表就方便了,右邊其實給出了這個公式,這裡的LR-UR-LL+UL就是整個綠色區域的像素值和。這個什麼道理其實已經自己可以推斷出來了, 如果還嫌這裡不清楚的話,我們就給個更清楚的圖:
這個圖和前面一樣,但是如果還是用LR-UR-LL+UL來表示的話,這裡就可以寫成:
LR-UR-LL+UL = (A+B+C+D)-(A+B)-(A+C)+A = D, 這樣就清楚很多了吧。 得到的這個值D就是D這個區域的像素值和, 那D中最中心的像素的顏色就可以用D/(widith*height)來做比較了。 所以算法的流程就是首先得到這個求和面積表, 其次遍歷所有的像素, 然後以這些像素為中心點, 計算S*S大小的矩形的平均顏色, 用來和當前像素比較即可。這個流程可以說是相當精煉啊!這裡依然用到了原來的S, T, 還保持了一致S是寬度的八分之一, 而T則是15,下面有一段我改過的實現代碼:
view plaincopy to clipboardprint?
void adaptiveThreshold(unsigned char* input, unsigned char*& bin, int width, int height)
{
int S = width >> 3;
int T = 15;
unsigned long* integralImg = 0;
int i, j;
long sum=0;
int count=0;
int index;
int x1, y1, x2, y2;
int s2 = S/2;
bin = new unsigned char[width*height];
// create the integral image
integralImg = (unsigned long*)malloc(width*height*sizeof(unsigned long*));
for (i=0; i<width; i++)
{
// reset this column sum
sum = 0;
for (j=0; j<height; j++)
{
index = j*width+i;
sum += input[index];
if (i==0)
integralImg[index] = sum;
else
integralImg[index] = integralImg[index-1] + sum;
}
}
// perform thresholding
for (i=0; i<width; i++)
{
for (j=0; j<height; j++)
{
index = j*width+i;
// set the SxS region
x1=i-s2; x2=i+s2;
y1=j-s2; y2=j+s2;
// check the border
if (x1 < 0) x1 = 0;
if (x2 >= width) x2 = width-1;
if (y1 < 0) y1 = 0;
if (y2 >= height) y2 = height-1;
count = (x2-x1)*(y2-y1);
// I(x,y)=s(x2,y2)-s(x1,y2)-s(x2,y1)+s(x1,x1)
sum = integralImg[y2*width+x2] -
integralImg[y1*width+x2] -
integralImg[y2*width+x1] +
integralImg[y1*width+x1];
if ((long)(input[index]*count) < (long)(sum*(100-T)/100))
bin[index] = 0;
else
bin[index] = 255;
}
}
free (integralImg);
}
這裡也有一點效果圖可以看看, 同時有和前面一個算法的比較:
原始1 wellnar算法 最新
還有一組:
wellnar:
最新算法:
這些個貼圖其實還不是特別的具體, 其實這個算法特別適用於光照強度變化很大的像素, 這裡有些網頁也給出了鮮明的對比:http://www.derekbradley.ca/AdaptiveThresholding/index.html
效果的差距還是很明顯的。 總的來說這個算法實現簡單, 效率很高,確實是不錯的選擇。 而且還很新!在07年的雜志上發表的,現在記錄下來與君共勉之!
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/hhygcy/archive/2009/06/18/4280165.aspx
http://www.derekbradley.ca/AdaptiveThresholding/index.html
Adaptive Thresholding Using the Integral Image
Derek Bradley and Gerhard Roth
Submission to ACM Journal of Graphics Tools
Source
The C/C++ implementation is available here: source.zip (144Kb)
留言列表