• Ostu方法又名最大类间差方法,通过统计整个图像的直方图特性来实现全局阈值T的自动选取,其算法步骤为: 1) 先计算图像的直方图,即将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量 2) 归一化...

    一、前言

    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值作为图像的全局阈值

    二、实现代码

    Ostu算法实现函数为下面中的int getOstu(const Mat& in),其实在opencv中已经在threshold中实现了,下面代码也比较了两者的结果

    #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("id_card.jpg" ,0);
    	Mat img_high_Light = imread("id_card2.jpg" ,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<<"\n"<<"The return value of opencv threshold is: "<<threshold(img , dst ,0,255,CV_THRESH_OTSU);//opencv已实现的大津法
    
    	imshow("光照均匀的原图像" ,img);
    	imshow("图像光照均匀的处理结果" , dst);
    
    	threshold(img_high_Light , dst_HL ,0,255,CV_THRESH_OTSU);
    	imshow("光照不均匀的原图像" ,img_high_Light );
    	imshow("图像光照不均匀的处理结果",  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;    
    }    
    三、运行结果

    调用函数getOstu和调用threshold所得到的图像全局阈值如下,可看出两者的结果非常接近,如下所示:

    当所处理图像光照均匀时,这时的分割效果较好,如下所示



    当处理的图像存在高照不均匀时,则ostu处理效果不是很好




    展开全文
  • ostu图像分割阈值算法matlab源程序
  • Ostu算法(又称为最大类间方差法)   图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有: 图像大小:M*N T为二值化的阈值; N0为灰度小于T的像素的个数,N0的平均灰度...

    Ostu算法(又称为最大类间方差法)
     

    图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有:

    图像大小:M*N

    T为二值化的阈值;

    N0为灰度小于T的像素的个数,N0的平均灰度为μ0

    N1 为灰度大于T的像素的个数,N1的平均灰度为μ1

    ω0=N0/ M×N (1)   //落在N0的概率

    ω1=N1/ M×N (2)  //落在N1的概率

    N0+N1=M×N (3)  

    ω0+ω1=1 (4)       

    μ=ω0*μ0+ω1*μ1 (5)  //平均灰度乘以概率 再相加

    g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)

    将式(5)代入式(6),得到等价公式: g=ω0ω1(μ0-μ1)^2 (7)   //g即为最类间差分

     

    遍历T, 取得使g最大的值,记录这时的T既是最佳阈值

    展开全文
  • Ostu算法与代码实例

    2019-07-18 21:34:50
    Otsu是图像处理中最常用的二值化算法,原理如下: 下面是用ostu算法对灰度图进行二值化处理的代码,用opencv写的 #include "opencv2/opencv.hpp" #include "opencv2/highgui/highgui.hpp" #include ...

       Otsu是图像处理中最常用的二值化算法,原理如下:

      

       

     下面是用ostu算法对灰度图进行二值化处理的代码,用opencv写的

    #include "opencv2/opencv.hpp"
    #include "opencv2/highgui/highgui.hpp"   
    #include "opencv2/imgproc/imgproc.hpp" 
    using namespace cv;
    
    int main()
    {
        Mat src = imread("D:\\picture\\1.jpg");
        if(!src.data)
            return -1;
        imshow("original",src);
        Mat gray ;
        cv::cvtColor(src,gray,CV_BGR2GRAY);
        imshow("gray",gray);
        int rows = gray.rows;
        int cols = gray.cols;
        float count[256] = {0};//每个灰度值[0,255]的计数
        for(int i = 0;i<rows;i++)
            for(int j = 0;j<cols;j++)
            {
                int index = (int)gray.at<uchar>(i,j);
                count[index]++;
            }
        float P[256];  //每个灰度值[0,255]的概率密度
        for(int i = 0;i<256;i++)
            P[i] = count[i]/(rows*cols);
        int threshold= 0;
        float deltaMax = 0;
        float w0,w1,u0tmp,u1tmp,u0,u1,ut,deltaTmp;
        for(int i = 1;i<256;i++)
        {
            w0 = w1 = u0tmp = u1tmp = u0 = u1 = ut = deltaTmp = 0;
            for(int j = 0;j<256;j++)
            {
                if(j<i)//背景
                {
                    w0 = w0+P[j];//背景像素占整幅图的比例
                    u0tmp = u0tmp + j*P[j];
                }
                else //前景
                {
                    w1 = w1+P[j];//前景占整幅图的比例
                    u1tmp = u1tmp + j*P[j];
                }
            }
            u0 = u0tmp/w0;//背景像素点的平均灰度
            u1 = u1tmp/w1;//前景像素点的平均灰度
            ut = w0*u0 + w1*u1; //整幅图像的平均灰度
            for(int k = 0;k<256;k++)
                deltaTmp = deltaTmp + (k-ut)*(k-ut)*P[k];//全局方差
            deltaTmp = w0*w1*(u1-u0)*(u1-u0)/deltaTmp;//类间方差除以全局方差
            if (deltaTmp>deltaMax)
            {
                deltaMax = deltaTmp;
                threshold = i;
            }
        }
        Mat binary_gray = gray.clone();
        for(int i = 0;i<rows;i++)
            for(int j = 0;j<cols;j++)
                if((int)gray.at<uchar>(i,j)<threshold)
                    binary_gray.at<uchar>(i,j) = (uchar)0;
                else
                    binary_gray.at<uchar>(i,j) = (uchar)255;
        imshow("binary_gray",binary_gray);
        waitKey(0);
        return 0;
    }

    接下来是运行的结果

     

     

    转载于:https://www.cnblogs.com/fishsorry/p/3647689.html

    展开全文
  • ostu算法---图像处理

    2020-04-12 23:31:17
    OTSU算法也称最大类间差法,有时也称之为大津算法,被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。它是按图像的灰度特性,将图像分成背景和...
  •  [函数名称] ... Ostu图像二值化 WriteableBitmap OstuThSegment(WriteableBitmap src) [函数代码] /// /// Ostu method of image segmention. /// /// The source image.
    

    [函数名称]

      Ostu法图像二值化      WriteableBitmap OstuThSegment(WriteableBitmap src)

    [函数代码]

            /// <summary>
            /// Ostu method of image segmention.
            /// </summary>
            /// <param name="src">The source image.</param>
            /// <returns></returns>
            public static WriteableBitmap OstuThSegment(WriteableBitmap src) ////Ostu法阈值分割
            {
                if (src != null)
                {
                    int w = src.PixelWidth;
                    int h = src.PixelHeight;
                    WriteableBitmap dstImage = new WriteableBitmap(w, h);
                    byte[] temp = src.PixelBuffer.ToArray();
                    byte[] tempMask = (byte[])temp.Clone();
                    //定义灰度图像信息存储变量
                    int[] srcData = new int[w * h];
                    //定义阈值变量
                    int Th = 0; ;
                    //定义背景和目标像素数目变量N1,N2,灰度变量U1,U2,灰度和变量Sum1,Sum2,临时缓存变量Temp
                    int N1 = 0, N2 = 0, Sum1 = 0, Sum2 = 0;
                    //定义背景和目标像素比例变量W1,W2,图像整体平均灰度变量U,方差变量g,对比阈值变量TT
                    double W1 = 0, W2 = 0, U1 = 0, U2 = 0, g = 0, TT = 0;
                    for (int j = 0; j < h; j++)
                    {
                        for (int i = 0; i < w; i++)
                        {
                            srcData[i + j * w] = (int)((double)tempMask[i * 4 + j * w * 4] * 0.114 + (double)tempMask[i * 4 + 1 + j * w * 4] * 0.587 + (double)tempMask[i * 4 + 2 + j * w * 4] * 0.299);
                        }
                    }
                    //寻找最大类间方差
                    for (int T = 0; T <= 255; T++)
                    {
                        for (int i = 0; i < srcData.Length; i++)
                        {
                            if (srcData[i] > T)
                            {
                                N2++;
                                Sum2 += srcData[i];
                            }
                            else
                            {
                                N1++;
                                Sum1 += srcData[i];
                            }
                        }
                        W1 = (double)(N1 / (N1 + N2));
                        W2 = (double)(1.0 - W1);
                        U1 = (N1 == 0 ? 0.0 : (Sum1 / N1));
                        U2 = (N2 == 0 ? 0.0 : (Sum2 / N2));
                        g = N1 * N2 * (U1 - U2) * (U1 - U2);
                        if (g > TT)
                        {
                            TT = g;
                            Th = T;
                        }
                        N1 = 0; N2 = 0;
                        Sum1 = 0; Sum2 = 0; W1 = 0.0; W2 = 0.0; U1 = 0.0; U2 = 0.0; g = 0.0;
                    }
                    for (int j = 0; j < h; j++)
                    {
                        for (int i = 0; i < w; i++)
                        {
                            temp[i * 4 + j * w * 4] = temp[i * 4 + 1 + j * w * 4] = temp[i * 4 + 2 + j * w * 4] = (byte)(srcData[i + j * w] < Th ? 0 : 255);
                        }
                    }
                    Stream sTemp = dstImage.PixelBuffer.AsStream();
                    sTemp.Seek(0, SeekOrigin.Begin);
                    sTemp.Write(temp, 0, w * 4 * h);
                    return dstImage;
                }
                else
                {
                    return null;
                }
            }

    展开全文
  • 一、算法简述 Otsu算法是一种用于二值化最佳阈值的选取方法。基本原理是根据阈值T将图像中的像素点分为C1和C2两类,不断的调整阈值T之后若此时两类之间存在最大的类间方差,那么此阈值即是最佳阈值。 二、算法...

    一、算法简述

           Otsu算法是一种用于二值化最佳阈值的选取方法。基本原理是根据阈值T将图像中的像素点分为C1和C2两类,不断的调整阈值T之后若此时两类之间存在最大的类间方差,那么此阈值即是最佳阈值。

    二、算法理论

      1、基础公式

          w_{1}=\sum_{i=0}^{k} p_{i}=w(k)                                                     (1)

          w_{2} = \sum_{i=k+1}^{L-1} p_{i} = 1-w(k)                                            (2)

         m_{1} = \sum_{i=0}^{k} \frac{ip_{i}}{w_{1}} = \frac{m(k)}{w(k)}                                                   (3)

        m_{2} = \sum_{i=k+1}^{L-1} \frac{ip_{i}}{w_{2}} = \frac{m-m(k)}{1-w(k)}                                         (4)

        m = \sum_{i=0}^{L-1} ip_{i}                                                                      (5)

        \sigma ^{2} = w_{1}(m_{1}-m)^{2} + w_{2}(m_{2}-m)^{2}                              (6)

        m = w_{1}m_{1} + w_{2}m_{2}                                                         (7)

        w_{1} + w_{2} = 1                                                                     (8)

    2、Otsu算法公式推导(为了减少计算量,所以对(6)式进行化简)

        利用(7)、(8)可将(6)化简成:

       \sigma ^{2} = w_{1}w_{2}(m_{1}-m_{2})^{2}                                                     (9)

       利用(3)、(4)可将(9)化简成:

       \sigma ^{2} = \frac{[mw(k)-m_{1}]^{2}}{w(k)[1-w(k)]}                                                        (10) 

      不断更改阈值T,,再利用(1)、(2)、(3)、(5)计算出(10)中的相关值计算出(10)中的最大方差值时,阈值T即为   最佳。

    三、算法实现(2020.2.4)

      1、matlab实现

    clear all
    PI = imread('E:\Image_Processing\Image_Repo\拉力表.jpg');
    subplot(1,2,1),imshow(PI);
    T = graythresh(PI);
    PO = im2bw(PI,T);
    subplot(1,2,2),imshow(PO);

      2、python实现

    # -*- coding: utf-8 -*-
    import sys
    import numpy as np
    import cv2
    import math
    #计算图像灰度直方图
    def calcGrayHist(image):
        #灰度图像矩阵的宽高
        rows,cols = image.shape
        #存储灰度直方图
        grayHist = np.zeros([1,256],np.uint32)
        for r in range(rows):
            for c in range(cols):
                grayHist[0][image[r][c]] +=1
        return grayHist         
    def ostu(image):
        rows,cols = image.shape
        #计算图像的灰度直方图
        grayHist = calcGrayHist(image)
        #归一化灰度直方图
        uniformGrayHist = grayHist/float(rows*cols)
        #计算零阶累积矩和一阶累积矩
        zeroCumuMoment = np.zeros([1,256],np.float32)
        oneCumuMoment = np.zeros([1,256],np.float32)
        for k in range(256):
            if k == 0:
                zeroCumuMoment[0][k] = uniformGrayHist[0][0]
                oneCumuMoment[0][k] = (k+1)*uniformGrayHist[0][0]
            else:
                zeroCumuMoment[0][k] = zeroCumuMoment[0][k-1] + uniformGrayHist[0][k]
                oneCumuMoment[0][k] = oneCumuMoment[0][k-1] + k*uniformGrayHist[0][k]
        #计算类间方差  
        variance = np.zeros([1,256],np.float32)
        for k in range(255):
            if zeroCumuMoment[0][k] == 0:
                variance[0][k] = 0
            else:
                variance[0][k] = math.pow(oneCumuMoment[0][255]*zeroCumuMoment[0][k] - oneCumuMoment[0][k],2)/(zeroCumuMoment[0][k]*(1.0-zeroCumuMoment[0][k]))
        #找到阈值
        threshLoc = np.where(variance[0][0:255] == np.max(variance[0][0:255]))
        thresh = threshLoc[0]
        #阈值处理
        threshold = np.copy(image)
        threshold[threshold > thresh] = 255
        threshold[threshold <= thresh] = 0
        return threshold
    #主函数
    if __name__ =="__main__":
        image = cv2.imread('E:\Image_Processing\Image_Repo\pull_Meter.jpg',cv2.IMREAD_COLOR)
        #显示原图
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        cv2.imshow("image",image)
        #阈值算法
        ostu_threshold = ostu(image)
        #显示阈值处理的结果
        cv2.imshow("ostu_threshold",ostu_threshold)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    

      3、c++实现

    四、后记:本文主要是本人在学习过程中的一些学习记录和心得,欢迎大家评论交流纠正。

    展开全文
  • 图像二值化算法图像处理的基础。一般来说,二值化算法可以分为两个类别:全局二值化和局部二值化。全局二值化是指通过某种算法找到一个全局的阈值T,对图像中坐标为(x,y)的像素值做如下处理: Ostu就是...
  • 1.Ostu算法原理 使用大津算法来二值化图像!大津算法,也被称作最大类间方差法,是一种可以自动确定二值化中阈值的算法,从类内方差和类间方差的比值计算得来: 小于阈值 t 的类记作 0,大于阈值 t 的类记作 1; ...
  • Ostu算法其实就是遍历每个灰度级,判断哪个灰度级的阈值分割的效果最佳,判断效果好坏的指标就是类间方差的大小,类将方差越大效果越好。 计算图像的归一化直方图 ```javascript // grayimg = rgb2gray(img);%将...
  • otsu算法 下面是我写的代码,也会参照别人写的 /** * @brief :直方图 统计各个灰度级的数量 * @param [in] : src_image 源图像 * height 高 * width 宽 * @param [out] : histogram 各个灰度级统计结果 * @...
  • OSTU(大津算法

    2018-03-29 22:18:25
    一、前言Ostu方法又名最大类间差方法,通过统计整个图像的直方图特性来实现全局阈值T的自动选取,其算法步骤为:1) 先计算图像的直方图,即将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量2) ...
  • //-----------------------------------OpenCV学习1-------------------...// 程序名称:OSTU算法选自适应阈值 // 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9) #include <opencv2\opencv.hpp> #inc
  • Ostu算法

    2016-05-24 21:32:05
    图像二值化算法图像处理的基础。一般来说,二值化算法可以分为两个类别:全局二值化和局部二值化。全局二值化是指通过某种算法找到一个全局的阈值T,对图像中坐标为(x,y)的像素值做如下处理:f(x,y)>T则f(x,y)=...
  • Ostu算法原理

    2019-10-08 14:56:22
    %使用OTSU算法进行二值化后的图像 close all;clear all;clc %% I = imread('C.jpg'); I=rgb2gray(I); %% I1=im2uint8(I(:)); depth=256; imhist(I1,depth); counts=imhist(I1,depth);%灰度直方图中,横坐标...
  • ostu图像分割阈值算法,对Ostu图像分割最优阈值进行优化处理,极大缩短了搜索图像阈值计算时间,与传统的枚举法Otsu方法相比,在计算时间上具有显著的优点。-
  • 关于对图像分割的Ostu全局阈值算法在遗传算法中的优化及实现
  • 一些基本数字图像处理算法 所有的图像算法都在DIPAlgorithm类中,并且所有算法都为抽象成员函数。我已经按照java注释规范为所有方法添加使用说明注释,具体实现可见于DIPAlgorithm.java,这里只做算法说明。 1 图像...
  • 图像分割中OTSU算法

    2015-04-20 22:28:33
    OTSU算法图像处理里面一个常用的方法,它主要用来自动的选择一个阈值,以此来对图片进行分割,更好的区别前景区域和背景区域。OTSU方法的思路比较简单,大体如下: 1. 将图像定义为两个部分,前景和背景; a....
  • 本人最近在做毕业设计,基于Matlab的植物叶脉提取,因为叶片采集过程中受光照影响比较大,所以如果直接用Ostu进行阈值分割,可以发现反光比较厉害的区域基本提取不出叶脉来,请问这样的情况应该用什么分割方法比较好...
1 2 3 4 5 ... 20
收藏数 594
精华内容 237