OSTU大律法二值化原理

来源:互联网 发布:沙袋绑腿 淘宝 编辑:程序博客网 时间:2024/06/05 19:14

介绍

Ostu方法又名最大类间差方法,通过统计整个图像的直方图特性来实现全局阈值T的自动选取,其算法步骤为:

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

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

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

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

5) 计算前景像素和背景像素的方差 g = w0*w1*(u0-u1) (u0-u1)

6) i++;转到4),直到i为256时结束迭代

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

代码:

#include <opencv2/opencv.hpp>#include <opencv2/core.hpp>#include <opencv2/imgproc.hpp>#include <opencv2/highgui.hpp>using namespace cv;using namespace std;//输入图像,输出阈值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 < width; 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);//对图像二值化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算法在处理光照不均匀的图像的时候,效果会明显不好,因为利用的是全局像素信息。

原创粉丝点击