灰度图像的阈值化

通过对灰度图像二值化处理,能够凸现出感兴趣目标的轮廓.

灰度图像的二值化处理就是讲图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适当的阀值选取而获得仍然可以反映图像整体和局部特征的二值化图像。在数字图像处理中,二值图像占有非常重要的地位,特别是在实用的图像处理中,以二值图像处理实现而构成的系统是很多的,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像,这样子有利于再对图像做进一步处理时,图像的集合性质只与像素值为0或255的点的位置有关,不再涉及像素的多级值,使处理变得简单,而且数据的处理和压缩量小。为了得到理想的二值图像,一般采用封闭、连通的边界定义不交叠的区域。所有灰度大于或等于阀值的像素被判定为属于特定物体,其灰度值为255表示,否则这些像素点被排除在物体区域以外,灰度值为0,表示背景或者例外的物体区域。如果某特定物体在内部有均匀一致的灰度值,并且其处在一个具有其他等级灰度值的均匀背景下,使用阀值法就可以得到比较的分割效果。如果物体同背景的差别表现不在灰度值上(比如纹理不同),可以将这个差别特征转换为灰度的差别,然后利用阀值选取技术来分割该图像。动态调节阀值实现图像的二值化可动态观察其分割图像的具体结果。

灰度图像的二值化没有固定的算法,根据图像区域中目标物体的不同而有不同的二值化算法.

实际使用中最简单的二值化算法就是根据每个像素的灰度值做舍入处理,比如二值化阀值可以设置为0-255的中值127,但是这种的二值化没有根基图像的整体灰度值所在范围做考虑,所以效果很差.

下面的算法是根据图像的直方图求取阀值:

c#算法:
//----------------------------------------------
private int ousu(Bitmap img)
  {
   intthresholdValue=1; // 阈值
   int[] ihist =new int[256]; // 图像直方图,256个点

   int i, j, k;// various counters
   int n, n1,n2, gmin, gmax;
   double m1,m2, sum, csum, fmax, sb;

   //对直方图置零...
   for(i=0;i<256;i++)
    ihist[i]= 0;
   //
   gmin=255;gmax=0;
   //生成直方图
   for (i = 1; i< img.Width - 1; i++)
   {
    for(j = 1; j < img.Height - 1; j++)
    {
     //该像素点的颜色灰度值
     //intc = img.getPixel(i,j).R;
     Colorc = img.GetPixel(i,j);
     intcn = ((c.G*59+c.R*30+c.B*11)/100);
     ihist[cn]++;
     //
     if(cn> gmax) gmax=cn;
     if(cn< gmin) gmin=cn;
    }
   }
   // set upeverything
   sum = csum =0.0;
   n = 0;
   for (k = 0; k<= 255; k++)
   {
    sum+= (double) k * (double) ihist[k];
    n+= ihist[k];
   }

   if(n==0)
   {
    //if n has no value, there is problems...
    return(60);
   }

   // do theotsu global thresholding method
   fmax =-1.0;
   n1 = 0;
   for (k = 0; k< 255; k++)
   {
    n1+= ihist[k];
    if(n1==0) { continue; }
    n2= n - n1;
    if(n2 == 0) { break; }
    csum+= (double) k *ihist[k];
    m1= csum / n1;
    m2= (sum - csum) / n2;
    sb= (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2);
    
    if(sb > fmax)
    {
     fmax= sb;
     thresholdValue= k;
    }
   }
   // at thispoint we have our thresholding value
   MessageBox.Show(thresholdValue.ToString());
   returnthresholdValue;


  }

//-----------------------------------------------------------------------

as算法:
//------------------------------------------------------------------------------------
//计算二值化阀值
//
function otsu (bmd:BitmapData)
{

var thresholdValue=1; // 阈值
var ihist = [256]; // 图像直方图,256个点

var i, j, k; // various counters
var n, n1, n2, gmin, gmax;
var m1, m2, sum, csum, fmax, sb;

// 对直方图置零...
for(i=0;i<256;i++)
ihist[i] = 0;
//
gmin=255; gmax=0;
// 生成直方图
for (i = 1; i < bmd.width - 1; i++) {
for (j = 1; j < bmd.height - 1; j++) {
  //该像素点的颜色灰度值
  var c =int("0x"+bmd.getPixel(i,j).toString(16).substr(2,2));
ihist[c]++;
  //
if(c > gmax) gmax=c;
if(c < gmin) gmin=c;
}
}
// set up everything
sum = csum = 0.0;
n = 0;
for (k = 0; k <= 255; k++) {
sum += k *ihist[k];
n += ihist[k];
}

if (!n) {
// if n has no value, there is problems...
return (60);
}

// do the otsu global thresholding method
fmax = -1.0;
n1 = 0;
for (k = 0; k < 255; k++) {
n1 += ihist[k];
if (!n1) { continue; }
n2 = n - n1;
if (n2 == 0) { break; }
csum += k *ihist[k];
m1 = csum / n1;
m2 = (sum - csum) / n2;
sb = n1 * n2 *(m1 - m2) * (m1 - m2);

if (sb > fmax) {
fmax = sb;
thresholdValue = k;
}
}
// at this point we have our thresholding value
return(thresholdValue);
}

 
原文地址:https://www.cnblogs.com/feisky/p/1586689.html