智能车视觉处理系列文章——二值化技巧(含代码)

文章目录

      • 图片二值化技巧
        • 1. 大津法(OTSU) 求阈值
          • 1.1 说明
          • 1.2 计算过程

图片二值化技巧

1. 大津法(OTSU) 求阈值

1.1 说明

​ 为了解决不同光照条件下,二值化阈值不同的问题,最显而易见的方法就是根据当前图片的亮度情况动态决定二值化阈值。一个显而易见的方法就是统计图片的灰度分布情况,然后取平均数或者中数作为二值化阈值。这种实现最为简单。然而这种方法却并不十分合理。由于是取中数或平均数,则意味着这种方法会极大的受到众数的影响。而实际情况,白色赛道在整张图像中的占比并不大,采用这种方式确定阈值不一定有效。

​ 大津法阈值采用最大类间方差的原理,适合于图像灰度分布整体呈现“双峰”的情况。大津法会自动找出一个阈值,使得分割后的两部分类间方差最大。由于比赛过程中,摄像头画幅中几乎只有白色赛道和蓝色底布,所以灰度分布比较符合**“双峰”这个条件**,大津法不失为一种不错的算法。

智能车视觉处理系列文章——二值化技巧(含代码)_第1张图片

1.2 计算过程
  • 先计算图像的直方图,即将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量

  • 归一化直方图,即将每个bin中像素点数量除以总的像素点。

  • i表示分类的阈值,也即一个灰度级,从0开始迭代。

  • 通过归一化的直方图,统计0~i 灰度级的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例 w 0 w_0 w0​​​,并统计前景像素的平均灰度 u 0 u_0 u0​​​​;统计i~255灰度级的像素(假设像素值在此范围的像素叫做背景像素) 所占整幅图像的比例 w 1 w_1 w1,并统计背景像素的平均灰度 u 1 u_1 u1​​​。

  • 计算总平均灰度 u = u 1 + u 0 u=u_1 + u_0 u=u1+u0

  • 计算前景像素和背景像素的方差 g = w 0 ∗ ( u 0 − u ) 2 + w 1 ∗ ( u 1 − u ) 2 g=w_0*(u_0-u)^2 + w_1*(u_1-u)^2 g=w0(u0u)2+w1(u1u)2​​​。​​

  • i++;转到第四步,直到i为256时结束迭代。

  • 将最大g相应的i值作为图像的全局阈值。

参考博文

uint8 otsuThreshold(uint8 *image, uint16 col, uint16 row)
{
    #define GrayScale 256
    uint16 width = col;
    uint16 height = row;
    int pixelCount[GrayScale];
    float pixelPro[GrayScale];
    int i, j, pixelSum = width * height;
    uint8 threshold = 0;
    uint8* data = image;  //指向像素数据的指针
    for (i = 0; i < GrayScale; i++)
    {
        pixelCount[i] = 0;
        pixelPro[i] = 0;
    }

    //统计灰度级中每个像素在整幅图像中的个数  
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            pixelCount[(int)data[i * width + j]]++;  //将像素值作为计数数组的下标
        }
    }

    //计算每个像素在整幅图像中的比例  
    float maxPro = 0.0;
    for (i = 0; i < GrayScale; i++)
    {
        pixelPro[i] = (float)pixelCount[i] / pixelSum;
        if (pixelPro[i] > maxPro)
        {
            maxPro = pixelPro[i];   //得到占比最大的??
        }
    }

    //遍历灰度级[0,255]  
    float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
    for (i = 0; i < GrayScale; i++)     // i作为阈值
    {
        w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = 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;
        u = u0tmp + u1tmp; // 像素总均值
        deltaTmp = w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);
        if (deltaTmp > deltaMax)
        {
            deltaMax = deltaTmp;
            threshold = i;
        }
    }

    return threshold;
}

此方法计算时间较长,优化大津法。

你可能感兴趣的:(智能车,计算机视觉,opencv,算法)