目录

  • 什么是二值化
  • 常见的求阈值算法
    • OSTU大津法
      • 概念及原理
    • iteration迭代法
      • 概念及原理
      • 代码实现
    • Sobel算子图像边缘提取
      • 概念及原理
      • 代码实现
      • 噪点过滤

什么是二值化

所谓图像二值化,就是将256个亮度等级的灰度图像,通过适当的阈值选取而获得仍然可以反映图像整体和局部特征的二值化图像。
由于我们用摄像头拍到的图像为灰度图像,若直接处理会加大很多不必要的工作量,而将图像二值化,则可以使目标图像变得简单且数据量小,同时又不丢失图像中的重要信息。

由此可见,在图像处理中,二值化步骤显得尤为重要。我们知道,二值化的步骤无非是将获得的图像数据中大于阈值的像素点用255表示,而小于阈值的像素点用0表示。
那么如何选择二值化所需的阈值,就成为了非常重要的一个步骤。

常见的求阈值算法

OSTU大津法

概念及原理

OTSU算法又称为最大类间方差法。这是我们很常见的一种求阈值的方法,它的思路就是通过统计整个图像的直方图特性来实现全局阈值T的自动选取。
该算法进行前先设一个i作为分类阈值,通过归一化的直方图,统计图像中各个灰度级的像素占整幅图像的比例w0,并统计前景像素和背景像素的平均灰度u0和u1,和背景像素所占比例w1;通过公式g = w0w1(u0-u1) (u0-u1)计算前景像素和背景像素的方差 ,每进行完一次循环i值加一,直道i=256时停止循环,并将最大的g值作为图像阈值。


大津法二值化的代码实现在网上比较多,这里不做详细介绍。

iteration迭代法

概念及原理

迭代法也叫最小概率误判法,它使用逐次逼近的思想,通过不断更新迭代,求出满足整幅图像偏差等级error的阈值。

具体步骤为:首先设定初始阈值T0和偏差等级,此阈值将图像分割为前景和背景,此时可以算出前景和背景的平均灰度值T1和T2,则新的最佳阈值为T_center=(T1+T2),将新阈值与上一个阈值比较。若两者之差在偏差等级之内,则将标志位置为0,结束运算,得到的阈值极为当前阈值;若大于此偏差,则标志位置为1,继续下一次循环运算,由此逐渐逼近真实阈值。

代码实现


 do{
  	for(i=0;i<MT9V03X_H;i++)
    {
      for(j=0;j<MT9V03X_W;j++)
      {
        if(Im[i][j] < T2)
        {
          S0 += Im[i][j];
          N0++;   //像素点数统计
        }
        else
        {
          S1 += Im[i][j];
          N1++;   //像素点数统计
        }
      }
    }
    T1 = S0/N0;   //平均灰度值
    T2 = S1/N1;   //平均灰度值
    T_center = (T1+T2)/2;
    
    if(abs(T_center - T0)> ERROR)   flag = 1;  
    else    flag = 0;
    T0 =T_center;
    BlackThres = T0;
  } while(flag);

迭代法的空间复杂度较高,且光照越强受到的影响越强。

Sobel算子图像边缘提取

概念及原理

索贝尔算子是计算机视觉领域的一种重要处理方法。主要用作边缘检测。索贝尔算子是把图像中每个像素的上下左右四领域的灰度值加权差,在边缘处达到极值从而检测边缘。

运算时我们对图像中每一点使用此算子,将会产生对应的梯度矢量或是其法矢量。
索贝尔算子包含两组3*3矩阵(横向与纵向),具体如下:(图源百度百科)

卷积因子
运算时将图像上每一点与其做平面卷积,即可分别得出横向及纵向的亮度差分近似值,公式如下:
在这里插入图片描述
再将Gx与Gy相加,即为该像素点的近似灰度大小。
最后我们可以使用像素点之和的一定比例,作为该图像阈值 。

代码实现

  	for (i = yStart; i < yEnd; i++)
  	{
   		 for (j = xStart; j < xEnd; j++)
            TempX=(-    mt9v03x_image[i-1][j-1])
                    +(-2*mt9v03x_image[i ][j-1])
                    +(-  mt9v03x_image[i+1][j-1])
                    +(   mt9v03x_image[i-1][j+1])
                    +( 2*mt9v03x_image[i  ][j+1])
                    +(   mt9v03x_image[i+1][j+1]);
        
            TempY=(     mt9v03x_image[i+1][j-1])
                    +( 2*mt9v03x_image[i+1][j  ])
                    +(   mt9v03x_image[i+1][j+1])
                    +(-  mt9v03x_image[i-1][j-1])
                    +(-2*mt9v03x_image[i-1][j  ])
                    +(-  mt9v03x_image[i-1][j+1]);
            temp=abs(tempx)+abs(tempy);
            if(temp>255)    temp=255;
            Image_Sobel[i][j]=temp;
    }

这种方法对阳光的适应性较好,空间复杂度也不大,是目前一种比较好的阈值算法。

噪点过滤

索贝尔算子有着较好的检测效果,并且对噪声具有平滑抑制的作用,但其得到的边缘较粗,且可能出现伪边缘。所以我们需要对其噪点进行过滤。

  for (nr = 1; nr < LCDH - 1; nr++)
  {
    for (nc = 1; nc < LCDW - 1; nc = nc + 1)
    {
            if(WhitePixle(i,j) && mt9v03x_image[i][j]>threshold)
                Image_Sobel[i][j] = 0xFE;
            if( BlackPixle(i-1,j-1)&&BlackPixle(i-1,j)&&BlackPixle(i-1,j+1)&&
                BlackPixle(i,j-1)&&BlackPixle(i,j+1)&&WhitePixle(i,j)&&
                BlackPixle(i+1,j-1)&&BlackPixle(i+1,j)&&BlackPixle(i+1,j+1))
                Image_Sobel[i][j] = 0xFE;
      }
  }

总结到这里就告一段落了,自我小结的同时,也希望或多或少可以对大家有所帮助