覺得這篇介紹OTSU方法挺清楚的。自己又加了一些,希望對初學者有協助哦~
轉載:http://blog.csdn.net/WuHaibing_CVer
OTSU演算法是由日本學者OTSU於1979年提出的一種對映像進行二值化的高效演算法。
1. OTSU演算法原理簡介
對於一幅映像,設當前景與背景的分割閾值為t時,前景點占映像比例為w0,均值為u0,背景點占映像比例為w1,均值為u1。則整個映像的均值為u = w0*u0+w1*u1。建立目標函數g(t)=w0*(u0-u)^2+w1*(u1-u)^2,g(t)就是當分割閾值為t時的類間方差運算式。OTSU演算法使得g(t)取得全域最大值,當g(t)為最大時所對應的t稱為最佳閾值。OTSU演算法又稱為最大類間方差法。
OSTU大津法演算法思想:
一幅有depth個灰階級,根據每個灰階級t,可以將一幅圖分為前景和背景。
前景指所有灰階級低於等於t的像素點,背景指大於t的像素點。
w0指前景像素個數;w1指背景像素個數;u0指前景加權平均,即
temp=0;
for i=1:t
temp=temp+i*hist(i)
end
u0=temp/w0;
其中w0=hist(0)+hist(1)+……+hist(t)
hist指各個灰階級上的像素個數
u1對應是背景加權平均
u對應整幅圖的加權平均
u=u0*w0+u1*w1.(*)
大津法的結果指使得g最大的t值:
g=w0*(u0-u)^2+w1*(u1-u)^2=w0*w1*(u1-u0)^2 (代入*式可得)
2.matlab提供演算法
function [level em] = graythresh(I)%GRAYTHRESH Global image threshold using Otsu's method.% LEVEL = GRAYTHRESH(I) computes a global threshold (LEVEL) that can be% used to convert an intensity image to a binary image with IM2BW. LEVEL% is a normalized intensity value that lies in the range [0, 1].% GRAYTHRESH uses Otsu's method, which chooses the threshold to minimize% the intraclass variance of the thresholded black and white pixels.%% [LEVEL EM] = GRAYTHRESH(I) returns effectiveness metric, EM, as the% second output argument. It indicates the effectiveness of thresholding% of the input image and it is in the range [0, 1]. The lower bound is% attainable only by images having a single gray level, and the upper% bound is attainable only by two-valued images.
function level = Mygraythresh(I)%GRAYTHRESH Global image threshold using Otsu's method.% LEVEL = Mygraythresh(I) computes a global threshold (LEVEL) that can be% used to convert an intensity image to a binary image with IM2BW. LEVEL% is a normalized intensity value that lies in the range [0, 1].% GRAYTHRESH uses Otsu's method, which chooses the threshold to minimize% the intraclass variance of the thresholded black and white pixels.%% Example% -------% I = imread('coins.png');% level = Mygraythresh(I);% BW = im2bw(I,level);% figure, imshow(BW)%% See also IM2BW.%I=rgb2gray(I);I=im2uint8(I(:));depth=256;counts=imhist(I,depth);w=cumsum(counts);ut=counts .* (1:depth)';u=cumsum(ut);MAX=0;level=0;for t=1:depth u0=u(t,1)/w(t,1); u1=(u(depth,1)-u(t,1))/(w(depth,1)-w(t,1)); w0=w(t,1); w1=w(depth,1)-w0; g=w0*w1*(u1-u0)*(u1-u0); if g > MAX MAX=g; level = t; endendlevel=level/256;3.OTSU演算法常式-C
下面是OSTU演算法的C語言代碼及其測試,代碼基於opencv。
#include <cv.h>#include <highgui.h>int otsu(IplImage *image){assert(NULL != image);int width = image->width;int height = image->height;int x=0,y=0;int pixelCount[256];float pixelPro[256];int i, j, pixelSum = width * height, threshold = 0;uchar* data = (uchar*)image->imageData;//初始化for(i = 0; i < 256; i++){pixelCount[i] = 0;pixelPro[i] = 0;}//統計灰階級中每個像素在整幅映像中的個數for(i = y; i < height; i++){for(j = x;j <width;j++){pixelCount[data[i * image->widthStep + j]]++;}}//計算每個像素在整幅映像中的比例for(i = 0; i < 256; i++){pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);}//經典ostu演算法,得到前景和背景的分割//遍曆灰階級[0,255],計算出方差最大的灰階值,為最佳閾值float w0, w1, u0tmp, u1tmp, u0, u1, u,deltaTmp, deltaMax = 0;for(i = 0; i < 256; i++){w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;for(j = 0; j < 256; j++){if(j <= i) //背景部分{//以i為閾值分類,第一類總的機率w0 += pixelPro[j];u0tmp += j * pixelPro[j];}else //前景部分{//以i為閾值分類,第二類總的機率w1 += pixelPro[j];u1tmp += j * pixelPro[j];}}u0 = u0tmp / w0;//第一類的平均灰階u1 = u1tmp / w1;//第二類的平均灰階u = u0tmp + u1tmp;//整幅映像的平均灰階//計算類間方差deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);//找出最大類間方差以及對應的閾值if(deltaTmp > deltaMax){deltaMax = deltaTmp;threshold = i;}}//返回最佳閾值;return threshold;}int main(int argc, char* argv[]){IplImage* srcImage = cvLoadImage("D:\\technology\\CV\\Database\\image\\rice.png",0);assert(NULL != srcImage);cvNamedWindow("src");cvShowImage("src",srcImage);IplImage* biImage = cvCreateImage(cvGetSize(srcImage),8,1);//計算最佳閾值int threshold = otsu(srcImage);//對映像二值化cvThreshold(srcImage,biImage,threshold,255,CV_THRESH_BINARY);cvNamedWindow("binary");cvShowImage("binary",biImage);cvWaitKey(0);cvReleaseImage(&srcImage);cvReleaseImage(&biImage);cvDestroyWindow("src");cvDestroyWindow("binary");return 0;}下面是上述代碼的運行結果圖片。其中左邊為原映像,右邊為使用OTSU演算法進行二值化後的映像。