最大類間分散法(大津法、OTSU)
3500 ワード
最大クラス間分散法は、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;