最大類間分散法(大津法、OTSU)


最大クラス間分散法は、1979年に日本の学者大津(Nobuyuki Otsu)が提案した適応しきい値決定法であり、大津法とも呼ばれ、OTSUと略称される.画像の階調特性に応じて、画像を背景とターゲットの2つの部分に分けます.背景とターゲットとの間のクラス間分散が大きいほど、画像を構成する2つの部分の差が大きいほど、部分的なターゲットが背景にずれたり、部分的な背景が間違ってターゲットに分かれたりすると、2つの部分の差が小さくなることを示します.したがって,クラス間分散を最大にする分割は,誤分確率が最小であることを意味する.画像I(x,y)については、前景(すなわち、目標)と背景との分割閾値を、前景に属する画素点数が画像全体に占める割合を、その平均階調とする.背景画素点数が画像全体に占める割合は、平均階調が.画像の総平均階調は,クラス間分散と記す.
画像の背景が暗く、画像の大きさが、画像中の画素の階調値が閾値より小さい画素個数を、画素の階調が閾値より大きい画素個数を、
       
遍歴法を用いてクラス間分散を最大にする閾値,すなわち求めた.
コード領域
OpenCV  :
int myOtsu(const IplImage *frame) //      
{
#define GrayScale 256	//frame   
	int width = frame->width;
	int height = frame->height;
	int pixelCount[GrayScale]={0};
	float pixelPro[GrayScale]={0};
	int i, j, pixelSum = width * height, threshold = 0;
	uchar* data = (uchar*)frame->imageData;

	//             
	for(i = 0; i < height; i++)
	{
		for(j = 0;j < width;j++)
		{
			pixelCount[(int)data[i * width + j]]++;
		}
	}

	//                    
	for(i = 0; i < GrayScale; i++)
	{
		pixelPro[i] = (float)pixelCount[i] / pixelSum;
	}

	//     [0,255],     threshold
	float w0, w1, u0tmp, u1tmp, u0, u1, deltaTmp, deltaMax = 0;
	for(i = 0; i < GrayScale; i++)
	{
		w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = 0;
		for(j = 0; j < GrayScale; j++)
		{
			if(j <= i)   //    
			{
				w0 += pixelPro[j];
				u0tmp += j * pixelPro[j];
			}
			else   //    
			{
				w1 += pixelPro[j];
				u1tmp += j * pixelPro[j];
			}
		}
		u0 = u0tmp / w0;
		u1 = u1tmp / w1;
		deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)) ;
		if(deltaTmp > deltaMax)
		{
			deltaMax = deltaTmp;
			threshold = i;
		}
	}
	return threshold;
}
MATLAB   1

function binariedImage=OSTU(scoreImage)

scoreImage=double(scoreImage);
[height,length]=size(scoreImage);
totalPixel=height*length;
% maxPixNumber=max(max(scoreImage));
%                              255

pixelCount=zeros(1,256);%          
% 0-256
for i=1:length
    for j=1:height
        number=scoreImage(j,i)+1;
        pixelCount(number)=pixelCount(number)+1;
    end
end

%  
pf=pixelCount/totalPixel;
%          
cpf=zeros(1,256);
cpf(1)=pf(1);
for i=2:256
    cpf(i)=cpf(i-1)+pf(i);
end
%          
bpf=zeros(1,256);
bpf(256)=pf(256);
for j=256:-1:2
    bpf(j-1)=bpf(j)+pf(j-1);
end 


%      
meanForward=zeros(1,256);
meanForward(1)=1;
for i=2:256
    meanForward(i)=meanForward(i-1)*(cpf(i-1)/cpf(i))+(pf(i)/cpf(i))*i;
end

%      
meanBack=zeros(1,256);
meanBack(max(max(scoreImage)))=max(max(scoreImage));
for i=max(max(scoreImage)):-1:2
    meanBack(i-1)=meanBack(i)*(bpf(i)/bpf(i-1))+(pf(i-1)/bpf(i-1))*(i-1);
end


delta=cpf.*bpf.*(meanForward-meanBack).^2;
[value,index]=max(delta);
%          
binariedImage=scoreImage>index;

MATLAB   2

function binariedImage=OSTU(scoreImage)


[height,length]=size(scoreImage);
totalNum=height*length;
pixelCount=zeros(1,256);%          
for i=1:length
    for j=1:height
        number=scoreImage(j,i)+1;
        pixelCount(number)=pixelCount(number)+1;
    end
end
pf=pixelCount/totalNum;
deltaMax=0;
a=1:256;
maxmax=max(max(scoreImage));
for i=1:maxmax
    
    w1=sum(pf(1:i));
    w2=1-w1;
    mean1=sum(pf(1:i).*a(1:i))/sum(pf(1:i));
    mean2=sum(pf(i+1:maxmax).*a(i+1:maxmax))/sum(pf(i+1:maxmax));
    delta=w1*w2*(mean1-mean2)^2;
    if delta>deltaMax
        deltaMax=delta;
        threshold=i;
    end
    
end

%          
binariedImage=scoreImage>threshold;