范文一:大津法原理(otsu)
最大类间方差法(大津法,OTSU)
最大类间方差法是由日本学者大津(Nobuyuki Otsu)于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。对于图像I(x,y),前景(即目标)和背景的分割阈值记作,属于前景的像素点数T
,,,占整幅图像的比例记为,其平均灰度;背景像素点数占整幅图像的比例为,其平均灰211
,度为。图像的总平均灰度记为,类间方差记为。 ,g2
假设图像的背景较暗,并且图像的大小为,图像中像素的灰度值小于阈值的像TMN,
NN素个数记作,像素灰度大于阈值的像素个数记作,则有: T12
N1 (1.1) ,,1,MN
N2 (1.2) ,,2,MN
NNMN,,, (1.3) 12
,,,,1 (1.4) 12
,,,,,,,,, (1.5) 1122
22g,,,,,,,,,,,,()() (1.6) 1122
将式(1.5)代入式(1.6),得到等价公式:
2g,,,,,,,,() (1.7) 1212
采用遍历的方法得到使类间方差最大的阈值,即为所求。 T
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 <>
{
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;
}
参考文献:Nobuyuki Otsu发表的原文
"A Threshold Selection Method from Gray-Level Histograms," Systems, Man and Cybernetics,
IEEE Transactions on , vol.9, no.1, pp.62-66, Jan. 1979
范文二:大津法原理(otsu)(可编辑)
大津法原理(otsu)
最大类间方差法 大津法,OTSU
最大类间方差法是由日本学者大津 Nobuyuki Otsu 于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。对于图像I x,y ,前景 即目标 和背景的分割阈值记作,属于前景的像素点数占整幅图像的比例记为,其平均灰度;背景像素点数占整幅图像的比例为,其平均灰度为。图像的总平均灰度记为,类间方差记为。
假设图像的背景较暗,并且图像的大小为,图像中像素的灰度值小于阈值的像素个数记作,像素灰度大于阈值的像素个数记作,则有:
将式 1.5 代入式 1.6 ,得到等价公式:
采用遍历的方法得到使类间方差最大的阈值,即为所求。
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, delta 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 delta
delta deltaTmp;
threshold i;
return threshold;
参考文献:Nobuyuki Otsu发表的原文
"A Threshold Selection Method from Gray-Level Histograms," Systems, Man and Cybernetics, IEEE Transactions on , vol.9, no.1, pp.62-66, Jan. 1979
范文三:大津法C++算法
最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均
灰度记为μ,类间方差记为g。假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有:
ω0=N0/ M×N (1)
ω1=N1/ M×N (2)
N0+N1=M×N (3)
ω0+ω1=1 (4)
μ=ω0*μ0+ω1*μ1 (5)
g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)
将式(5)代入式(6),得到等价公式:
g=ω0ω1(μ0-μ1)^2 (7)
采用遍历的方法得到使类间方差最大的阈值T,即为所求。
int Otsu(long *pg, long *pg1) // 大津法取阈值
{
int i,j,p;
double A,B,An,Bn,u,v,qqq[256],max,min;
An=Bn=0;
for (i=0;i<>
{
An+=pg;
Bn+=pg*(i+1);
}
for (j=0;j<>
{
A=B=0;
for (i=0;i<>
{
A+=pg;
B+=pg*(i+1);
}
if (A) u=B/A;
else u=0;
if (An-A) v=(Bn-B)/(An-A);
else v=0;
qqq[j]=A*(An-A)*(u-v)*(u-v); // 计算类间方差
}
max=min=qqq[0]; p=0;
for (i=1;i<256;i++)>256;i++)>
{
if (qqq>max)
{
max=qqq;
p=i;
}
else if (qqq
}
if (pg1!=0)
{
for (i=0;i<>
{
pg1=(long) (120*(qqq-min)/(max-min));
}
}
return(p); // 取判别函数最大值的灰度为其阈值
}
范文四:opencv大津法阈值分割
#include #include #include #include #include #include //#define Struct_size 11 //int flag_color; int hei; int wid; void otsu(IplImage* A, IplImage* B) { long N = hei * wid; int h[256]; double p[256],u[256],w[256]; for(int i = 0; i < 256;="" i++)="" {=""> h[i] = 0; p[i] = 0; u[i] = 0; w[i] = 0; } for(i = 0; i < hei;="" i++)="" {=""> for(int j = 0; j < wid;="" j++)=""> { for(int k = 0; k < 256;="" k++)=""> { if(((uchar*)(A->imageData + A->widthStep*i))[j] == k) { h[k]++; } } } } for(i = 0; i < 256;="" i++)=""> p[i] = h[i] / double(N); int T = 0; double uT,thegma2fang; double thegma2fang_max = -10000; for(int k = 0; k < 256;="" k++)=""> { uT = 0; for(i = 0; i <= k;="" i++)="">=> { u[k] += i*p[i]; w[k] += p[i]; } for(i = 0; i < 256;="" i++)=""> uT += i*p[i]; thegma2fang = (uT*w[k] - u[k])*(uT*w[k] - u[k]) / (w[k]*(1-w[k])); if(thegma2fang > thegma2fang_max) { thegma2fang_max = thegma2fang; T = k; } } for(i = 0; i < hei;="" i++)=""> { for(int j = 0; j < wid;="" j++)=""> { if(((uchar*)(A->imageData + A->widthStep*i))[j] > T) ((uchar*)(B->imageData + B->widthStep*i))[j] = 255; else ((uchar*)(B->imageData + B->widthStep*i))[j] = 0; } } } int main(int argc, char** argv) { //const char* filename = argc >= 2 ? argv[1] : "pic1.png"; const char* filename = "green001.bmp"; /* IplImage* InPut = cvCreateImage(cvSize(1600,1200), IPL_DEPTH_8U, 1); InPut = cvLoadImage( filename, 0 );*/ IplImage* InPut = cvLoadImage( filename, 0 ); IplImage *OutPut = cvCreateImage(cvSize(InPut->width,InPut->height),IPL_DEPTH_8U,1); hei = InPut->height; wid = InPut->width; otsu(InPut,OutPut); cvNamedWindow( "Resource", 1 ); cvShowImage( "Resource", InPut ); cvNamedWindow( "Result", 1 ); cvShowImage( "Result", OutPut ); cvWaitKey(0); return 0; } 二维OTSU算法实现C++源码 // 二维OTSU算法实现.cpp : 定义控制台应用程序的入口点。 #include "stdafx.h" #include #include #include #include #include int OTSU2d(IplImage * src) { int height = src->height; int width = src->width; long pixel = height * width; int histogram[256][256]; inti,j; for (i = 0;i < 256;i++)//初始化直方图=""> { for (j = 0; j < 256;j++)=""> histogram[i][j] = 0; } IplImage * temp = cvCreateImage(cvGetSize(src),8,1); cvSmooth(src,temp,CV_BLUR,3,0); for (i = 0;i { for (j = 0; j { int data1 = cvGetReal2D(src,i,j); int data2 = cvGetReal2D(temp,i,j); histogram[data1][data2]++; } } doublep_histogram[256][256]; for (i = 0; i < 256;i++)//直方图归一化=""> for(j = 0; j < 256;j++)=""> p_histogram[i][j] = (histogram[i][j]*1.0)/(pixel*1.0); double Pst_0[256][256];//Pst_0用来存储概率分布情况 Pst_0[0][0] = p_histogram[0][0]; for(i = 0;i < 256;i++)//计算概率分布情况=""> for(j = 0;j < 256;j++)=""> { double temp = 0.0; if(i-1 >= 0) temp = temp + Pst_0[i-1][j]; if(j-1 >= 0) temp = temp + Pst_0[i][j-1]; if(i-1 >= 0 && j-1 >= 0) temp = temp - Pst_0[i-1][j-1]; temp = temp + p_histogram[i][j]; Pst_0[i][j] = temp; } double Xst_0[256][256];//存储x方向上的均值矢量 Xst_0[0][0] = 0 * Pst_0[0][0]; for(i = 0 ; i < 256;i++)//计算x方向上的均值矢量=""> for(j = 0 ; j < 256;j++)=""> { double temp = 0.0; if(i-1 >= 0) temp = temp + Xst_0[i-1][j]; if(j-1 >= 0) temp = temp + Xst_0[i][j-1]; if(i-1 >= 0 && j-1 >= 0) temp = temp - Xst_0[i-1][j-1]; temp = temp + i * p_histogram[i][j]; Xst_0[i][j] = temp; } double Yst_0[256][256];//存储y方向上的均值矢量 Yst_0[0][0] = 0 * Pst_0[0][0]; for(i = 0 ; i < 256;i++)//计算y方向上的均值矢量=""> for(j = 0 ; j < 256;j++)=""> { double temp = 0.0; if(i-1 >= 0) temp = temp + Yst_0[i-1][j]; if(j-1 >= 0) temp = temp + Yst_0[i][j-1]; if(i-1 >= 0 && j-1 >= 0) temp = temp - Yst_0[i-1][j-1]; temp = temp + j * p_histogram[i][j]; Yst_0[i][j] = temp; } int threshold1; int threshold2; double variance = 0.0; doublemaxvariance = 0.0; for(i = 0;i < 256;i++)//计算类间离散测度=""> for(j = 0;j < 256;j++)=""> { long double p0 = Pst_0[i][j]; long double v0 = pow(((Xst_0[i][j]/p0)-Xst_0[255][255]),2) + pow(((Yst_0[i][j]/p0)-Yst_0[255][255]),2); long double p1 = Pst_0[255][255]-Pst_0[255][j]-Pst_0[i][255]+Pst_0[i][j]; long double vi = Xst_0[255][255]-Xst_0[255][j]-Xst_0[i][255]+Xst_0[i][j]; long double vj = Yst_0[255][255]-Yst_0[255][j]-Yst_0[i][255]+Yst_0[i][j]; long double v1 = pow(((vi/p1)-Xst_0[255][255]),2)+pow(((vj/p1)-Yst_0[255][255]),2); variance = p0*v0+p1*v1; if(variance >maxvariance) { maxvariance = variance; threshold1 = i; threshold2 = j; } } //printf("%d %d",threshold1,threshold2); return (threshold1+threshold2)/2; } int _tmain(intargc, _TCHAR* argv[]) { const char * filename = "rice.jpg"; IplImage * img = cvLoadImage(filename,0); IplImage * dst = cvCreateImage(cvGetSize(img),8,1); int threshold = OTSU2d(img); cvThreshold(img,dst,threshold,255,CV_THRESH_BINARY); cvNamedWindow( "img", 1 ); cvShowImage("img", dst); cvWaitKey(-1); return 0; } 转载请注明出处范文大全网 » 大津法原理(otsu)范文五:二位OTSU大津法阈值分割C++实现源码