ostu简写

图像二值化算法是图像处理的基础。一般来说,二值化算法可以分为两个类别:全局二值化和局部二值化。全局二值化是指通过某种算法找到一个全局的阈值T,对图像中坐标为(x,y)的像素值做如下处理:

Ostu就是这样一种全局二值化算法,又叫最大类间方差。因为该算法会遍历图像中任意一个像素值i,计算当其为阈值时,图像的前景和背景图像(并不一定是真正的前景和背景,只是我们把当前小于i的记做背景,大于i的记做前景)的方差值。当方差值达到最大时,我们认为此时的i是该图像的全局阈值。

符号说明:

前景点数占图像比例:w0;平均灰度:u0

背景点数占图像比例:w1,平局灰度:u1

图像平均灰度:

前景和背景图像方差:


但该算法也有一定的缺陷,即当分割图像的灰度直方图的双峰不太明显时,分割结果通常不太满意。付忠良提出了对OTSU算法的推广,将图像灰度的对比度即平均方差也考虑到阈值选择的影响因素中去,图像的目标与背景区内部一般较均匀,即对比度较小,而边界及其附近点的灰度跃变常常较大,即对比度较大,因此平均方差近似地反映了图像边界点的灰度跃变情况。
付忠良的方法希望分割出的目标和背景的均值和平均方差都远离全图的均值和平均方差,即目标和背景的平均灰度和对比度都远离全图的平均灰度和对比度。
平均方差λ为 

   ostu简写_第1张图片ostu简写_第2张图片

ostu简写_第3张图片ostu简写_第4张图片

#include
#include


int otsu(IplImage *image)
{
    assert(NULL != image);


    int width = image->width;
    int height = image->height;
    int x = 0, y = 0;
    int pixelCount[256];
    float pixelPro[256];
    int i, j, pixelSum = width * height, threshold = 0;


    uchar* data = (uchar*)image->imageData;


    //初始化
    for (i = 0; i < 256; i++)
    {
        pixelCount[i] = 0;
        pixelPro[i] = 0;
    }


    //统计灰度级中每个像素在整幅图像中的个数
    for (i = y; i < height; i++)
    {
        for (j = x; j         {
            pixelCount[data[i * image->widthStep + j]]++;
        }
    }


    //计算每个像素在整幅图像中的比例
    for (i = 0; i < 256; i++)
    {
        pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);
    }


    //经典ostu算法,得到前景和背景的分割
    //遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值
    float w0, w1, u0tmp, u1tmp, u0, u1, u, deltaTmp, deltaMax = 0;
    for (i = 0; i < 256; i++)
    {
        w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;


        for (j = 0; j < 256; j++)
        {
            if (j <= i) //背景部分
            {
                //以i为阈值分类,第一类总的概率
                w0 += pixelPro[j];
                u0tmp += j * pixelPro[j];
            }
            else       //前景部分
            {
                //以i为阈值分类,第二类总的概率
                w1 += pixelPro[j];
                u1tmp += j * pixelPro[j];
            }
        }


        u0 = u0tmp / w0;        //第一类的平均灰度
        u1 = u1tmp / w1;        //第二类的平均灰度
        u = u0tmp + u1tmp;        //整幅图像的平均灰度
        //计算类间方差
        deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);
        //找出最大类间方差以及对应的阈值
        if (deltaTmp > deltaMax)
        {
            deltaMax = deltaTmp;
            threshold = i;
        }
    }
    //返回最佳阈值;
    return threshold;
}


int main(int argc, char* argv[])
{
    IplImage* srcImage = cvLoadImage("1.jpg", 0);
    assert(NULL != srcImage);


    cvNamedWindow("src");
    cvShowImage("src", srcImage);


    IplImage* biImage = cvCreateImage(cvGetSize(srcImage), 8, 1);


    //计算最佳阈值
    int threshold = otsu(srcImage);
    printf("threshold = %d\n", threshold);
    //对图像二值化
    cvThreshold(srcImage, biImage, threshold, 255, CV_THRESH_BINARY);


    cvNamedWindow("binary");
    cvShowImage("binary", biImage);


    cvWaitKey(0);


    cvReleaseImage(&srcImage);
    cvReleaseImage(&biImage);
    cvDestroyWindow("src");
    cvDestroyWindow("binary");


    return 0;
}

你可能感兴趣的:(ostu简写)