zoukankan      html  css  js  c++  java
  • OSTU二值化算法

    介绍

    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/core/core.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    
    using namespace cv;
    
    #include <iostream>
    
    int getOstu(const Mat & in);
    
    int main()
    {
    	Mat img = imread("mobile2.jpeg" ,0);
    	Mat img_high_Light = imread("mobile3.jpeg" ,0);
    	Mat  dst , dst_HL;
    
    	if(img.empty()  | img_high_Light.empty())
    	{
    		std::cout<<"Error!!";
    		return -1;
    	}
    
    	std::cout<<"The return value of getOstu is: "<<getOstu(img);
    	std::cout<<"
    "<<"The return value of opencv threshold is: "<<threshold(img , dst ,0,255,CV_THRESH_OTSU);//opencv已实现的大津法
    
    	imshow("origin" ,img);
    	imshow("new" , dst);
    
        waitKey(0);
    
    	threshold(img_high_Light , dst_HL ,0,255,CV_THRESH_OTSU);
    	imshow("origin" ,img_high_Light );
    	imshow("new",  dst_HL);
    
    
    	waitKey(0);
    
    	return 0;
    }
    
    int getOstu(const Mat & in)
    {
    	int rows = in.rows;
    	int cols = in.cols;
    	long size = rows * cols;
    
    	float histogram[256] = {0};
    	for( int i = 0; i < rows; ++i)
    	{
    		//获取第 i行首像素指针
    		const uchar * p = in.ptr<uchar>(i);
    		//对第i 行的每个像素(byte)操作
    		for( int j = 0; j < cols; ++j )
    		{
    			histogram[int(*p++)]++;
    		}
    	}
    	int threshold;
    	long sum0 = 0, sum1 = 0; //存储前景的灰度总和及背景灰度总和
    	long cnt0 = 0, cnt1 = 0; //前景的总个数及背景的总个数
    	double w0 = 0, w1 = 0; //前景及背景所占整幅图像的比例
    	double u0 = 0, u1 = 0;  //前景及背景的平均灰度
    	double variance = 0; //最大类间方差
    
    
    	double maxVariance = 0;
    	for(int i = 1; i < 256; i++) //一次遍历每个像素
    	{
    		sum0 = 0;
    		sum1 = 0;
    		cnt0 = 0;
    		cnt1 = 0;
    		w0 = 0;
    		w1 = 0;
    		for(int j = 0; j < i; j++)
    		{
    			cnt0 += histogram[j];
    			sum0 += j * histogram[j];
    		}
    
    		u0 = (double)sum0 /  cnt0;
    		w0 = (double)cnt0 / size;
    
    		for(int j = i ; j <= 255; j++)
    		{
    			cnt1 += histogram[j];
    			sum1 += j * histogram[j];
    		}
    
    		u1 = (double)sum1 / cnt1;
    		w1 = 1 - w0; // (double)cnt1 / size;
    
    		variance =  w0 * w1 *  (u0 - u1) * (u0 - u1);
    		if(variance > maxVariance)
    		{
    			maxVariance = variance;
    			threshold = i;
    		}
    	}
    
    	return threshold;
    }
    

    缺陷

    OSTU算法在处理光照不均匀的图像的时候,效果会明显不好,因为利用的是全局像素信息。

  • 相关阅读:
    linux会话浅析
    linux memory lock浅析
    浅谈动态库符号的私有化与全局化
    LINUX内核内存屏障
    linux内存屏障浅析
    linux内核mem_cgroup浅析
    记一个linux内核内存提权问题
    linux内核cfs浅析
    linux内核tmpfs/shmem浅析
    linux IPv4报文处理浅析
  • 原文地址:https://www.cnblogs.com/zhonghuasong/p/7250540.html
Copyright © 2011-2022 走看看