图像二值化算法比较

要写论文了,就整理了下图像二值方面的算法及性能比较,记在这里。

此篇介绍两种全局阈值方法,下篇介绍自适应方法。

1:经典算法OTSU

OTSU的中心思想是阈值T应使目标与背景两类的类间方差最大。

//用类间方差最大思想计算阈值

int Threshold(int *hist)  //compute the threshold
{
 float u0, u1;
 float w0, w1;
 int count0;
 int t, maxT;
 float devi, maxDevi = 0; //方差及最大方差
 int i;
 int sum = 0;
 for (i = 0; i < 256; i++)
 {
  sum = sum + hist[i];
 }
 for (t = 0; t < 255; t++)
 {
  u0 = 0; count0 = 0;
  //阈值为t时,c0组的均值及产生的概率
  for (i = 0; i <= t; i++)
  {
   u0 += i * hist[i]; count0 += hist[i];
  }
  u0 = u0 / count0; w0 = (float)count0/sum;
  //阈值为t时,c1组的均值及产生的概率
  u1 = 0;
  for (i = t + 1; i < 256; i++)
  {
   u1 += i * hist[i]; 
  }
  u1 = u1 / (sum - count0); w1 = 1 - w0;

  //两类间方差
  devi = w0 * w1 * (u1 - u0) * (u1 - u0);
  //记录最大的方差及最佳位置
  if (devi > maxDevi)
  {
   maxDevi = devi;
   maxT = t;
  }
 }
 return maxT;
}

//二值化处理
void OTSU(IplImage *src, IplImage *dst)
{
 int i = 0, j = 0;
 int wide = src->widthStep;
 int high = src->height;
 int hist[256] = {0};
 int t;
 unsigned char *p, *q;
 for (j = 0; j < high; j ++)
 {
  p = (unsigned char *)(src->imageData + j * wide);
  for (i = 0; i < wide; i++)
  {
   hist[p[i]]++;   //统计直方图
  }
 }
 t = Threshold(hist);

 for (j = 0; j < high; j ++)
 {
  q = (unsigned char *)(dst->imageData + j * wide);
  p = (unsigned char *)(src->imageData + j * wide);
  for (i = 0; i < wide; i++)
  {
   q[i] = p[i] >= t ? 255 : 0;
  }
 }
}

      

OTSU算法对不均匀光照的图片不能产生很好的效果。

2:另外一个Kittler算法,是一种快速的全局阈值法。它的效果不比OTSU差多少,但速度快好多倍,如果可以应用在图像质量不错的环境。

它的中心思想是,计算整幅图像的梯度灰度的平均值,以此平均值做为阈值。

//kittler算法
  for (i=1;i<high-1;i++)             
 {
  plineadd=src->imageData+i*wide;
  pNextLine=src->imageData+(i+1)*wide;
  pPreLine=src->imageData+(i-1)*wide; 
  for(j=1;j<wide-1;j++)
  {

//求水平或垂直方向的最大梯度
   Grads=MAX(abs((uchar)pPreLine[j]-(uchar)pNextLine[j]),abs((uchar)plineadd[j-1]-(uchar)plineadd[j+1])); //max(xGrads,yGrads)
   sumGrads += Grads;

//梯度与当前点灰度的积
   sumGrayGrads += Grads*((uchar)plineadd[j]);   
  }
 }
 threshold=sumGrayGrads/sumGrads;
// printf("%d\n",threshold);
 for(i=0;i<high;i++)
 { 
  plineadd=src->imageData+i*wide;
  pTempLine=kittler->imageData+i*wide;
  for(j=0;j<wide;j++)
  {
   pTempLine[j]=(uchar)plineadd[j]>threshold?255:0;
  }
 }

转载于:https://www.cnblogs.com/lingde27/archive/2011/04/29/2032570.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值