图像分割之一维最大熵阈值分割方法

阈值分割是一种常用的图像分割方法,基于灰度阈值的选取将图像灰度划分为一个或几个集合,实现图像的分割。

阈值分割方法的关键是阈值选取准则,常用的准则有最大类间方差(OTSU 大津法)和信息熵。

信息熵包括很多种:一维最大熵,二维最大熵,交叉熵,待分割目标与背景最大类间交叉熵,分割前后图像间最小交叉熵等。

信息熵表示从信息源中可能获得的信息的大小。假设事件xi发生的概率为,其自信息量定义为pi:

自信息量的数学期望称为事件xi的信息熵,表示事件在不同发生概率时的信息量。统计每个灰度值像素点的个数以及概率,灰度值t把图像分为目标和背景,计算目标与背景中灰度值像素点的概率和w1,w2、分别得到目标信息熵与背景信息熵H1、H2,以目标和背景信息熵总和最大时的灰度值t为最终的分割阈值。具体步骤如下:

设图像的总像素个数为M*N,图像灰度级的概率分布为:

                

式中表示灰度级为i的像素点个数。背景包含的像素点的灰度范围为,运动目标包含的像素点灰度范围为。背景的灰度分布概率为:

                                

运动目标的灰度分布概率为:

                              

背景的信息熵为:

                     

运动目标的信息熵为:

                     

总信息熵为:

                          

t*为图像一维信息熵最大时的灰度值,及分割阈值。

opencv代码

int entropy( Mat image)  

{  
    float N=image.cols*image.rows;
int bins = 256;  
int hist_size[] = {bins};  
float range[] = { 0, 256 };  
const float* ranges[] = {range};  
MatND hist; 
int channels[] = {0};
calcHist( &image, 1, channels, Mat(), hist, 1, hist_size, ranges,true,false );//do not use mask  the histogram is uniform 
vector<float> f,p;
for(int i=0;i<bins;i++)
f.push_back(hist.at<float>(i));
float sum_f=0;
int size=f.size();
for(int i=0;i<size;i++)
sum_f=sum_f+f[i];
for(int i=0;i<size;i++)
{
p.push_back(f[i]/sum_f);
}
double Wb[256]={0},Wo[256]={0},Hb[256]={0},Ho[256]={0},Hs[256]={0};
for(int t=0;t<255;t++)
{
for(int i=0;i<=t;i++)
{
Wb[t]+=p[i];
}
for(int i=t+1;i<=254;i++)
{
Wo[t]+=p[i];
}

for(int i=0;i<=t;i++)
{
if(p[i]!=0)
Hb[t]+=(p[i]/Wb[t])*log(float(p[i]/Wb[t]));
}
for(int i=t+1;i<255;i++)   //出现除零错误
{
if(p[i]!=0)
Ho[t]+=(p[i]/Wo[t])*log(float(p[i]/Wo[t]));
}
}
for(int t=0;t<255;t++)
{
Hs[t]=Hb[t]+Ho[t];
}


float min=Hs[0];
int n=0;
for(int t=1;t<255;t++)
{
if(Hs[t]<min)
{
min=Hs[t];
   n=t;
}
}
cout<<n<<endl;
return n;
}
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页