OTSU(大津律法)数学原理及源码解析

本篇博客在书写过程中参考了一下两篇博客,在此贴出来,以示对原创者的尊重:OTSU算法(大津法—最大类间方差法)原理及实现详细及易读懂的 大津法(OTSU)原理 和 算法实现。再次向二位大佬致敬!

1.OTSU(最大类间差法):

OTST算法是用来对灰度图像(单通道)图像进行二值化阈值分割的基础图像分割算法,利用此方法进行图像二值化分割后,前景与背景图像的类间方差最大
常用场合:求解图像的全局最佳阈值。(原因如下:OTSU按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。)
缺点**:**对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,这个时候效果不好。

2.OTSU具体数学原理

(1)背景像素占比:: 在这里插入图片描述

其中(N1代表前景像素的个数,S代表图像总的像素数)
(2)前景像素占比: 在这里插入图片描述

(3)背景像素的平均灰度值: 在这里插入图片描述
(其中,Pi表示的是背景中,灰度值为i的像素点的个数,μt1表示的是背景像素相对于整个图像的灰度的数学期望值。)
(4)前景像素的平均灰度值: 在这里插入图片描述
(其中,μt2表示的是前景像素相对于整个图像的灰度到的数学期望值。)
(5) 0-M灰度范围内的图像的灰度均值:在这里插入图片描述

(6)类间方差: 在这里插入图片描述

(7)将(5)代入(6)得:在这里插入图片描述

3.OTSU源码及应用示例。

# -*- coding: utf-8 -*-
"""
Created on Thu Apr 23 17:48:57 2020

@author: Administrator
"""
'''
OTSU算法详解:
(1)背景像素占比:  (N1代表前景像素的个数,S代表图像总的像素数)
(2)前景像素占比:  
(3)背景像素的平均灰度值:  (其中,Pi表示的是背景中,灰度值为i的像素点的个数,μt1表示的是背景像素相对于整个图像的灰度的数学期望值。)
(4)前景像素的平均灰度值: (其中,μt2表示的是前景像素相对于整个图像的灰度到的数学期望值。) 
(5) 0-M灰度范围内的图像的灰度均值:: 
(6)类间方差:  
(7)将(5)代入(6)得:  

'''
import numpy as np
import cv2


class OTSU_Segmentation():
    def __init__(self,filename):
        self.source_img=cv2.imread(filename)
        self.u1=0.0#背景像素的平均灰度值
        self.u2=0.0#前景像素的平均灰度值
        self.th=0.0
    '''
    OTSU实现
    '''
    def CalTh(self,GrayScale):
        img_gray=cv2.cvtColor(self.source_img,cv2.COLOR_BGR2GRAY)
        img_gray=np.array(img_gray).ravel().astype(np.uint8)
       
        #总的像素数目
        PixSum=img_gray.size
        #各个灰度值的像素数目
        PixCount=np.zeros(GrayScale)
        #各灰度值所占总像素数的比例
        PixRate=np.zeros(GrayScale)
        #统计各个灰度值的像素个数
        for i in range(PixSum):
            #默认灰度图像的像素值范围为GrayScale
            Pixvalue=img_gray[i]
            PixCount[Pixvalue]=PixCount[Pixvalue]+1
        
        #确定各个灰度值对应的像素点的个数在所有的像素点中的比例。
        for j in range(GrayScale):
            PixRate[j]=PixCount[j]*1.0/PixSum
        Max_var = 0
        #确定最大类间方差对应的阈值

        for i in range(1,GrayScale):#从1开始是为了避免w1为0.
            u1_tem=0.0
            u2_tem=0.0
            #背景像素的比列
            w1=np.sum(PixRate[:i])
            #前景像素的比例
            w2=1.0-w1
            if w1==0 or w2==0:
                pass
            else:#背景像素的平均灰度值
                for m in range(i):
                    u1_tem=u1_tem+PixRate[m]*m
                self.u1=u1_tem*1.0/w1
            #前景像素的平均灰度值
                for n in range(i,GrayScale):
                    u2_tem=u2_tem+PixRate[n]*n
                self.u2=u2_tem/w2
                #print(self.u1)
            #类间方差公式:G=w1*w2*(u1-u2)**2
                tem_var=w1*w2*np.power((self.u1-self.u2),2)
                #print(tem_var)
            #判断当前类间方差是否为最大值。
                if Max_var<tem_var:
                    Max_var=tem_var#深拷贝,Max_var与tem_var占用不同的内存空间。
                    self.th=i
        #print(self.th)
    def Otsu_translation(self):
        img_g=cv2.cvtColor(self.source_img,cv2.COLOR_BGR2GRAY)
        
        result,img_seg=cv2.threshold(img_g,self.th,255,cv2.THRESH_BINARY)
        print(result)
        cv2.imwrite('1_seg.jpg',img_seg)
        cv2.imshow('The result of OTSU segtaton',img_seg)
        cv2.waitKey(0)
otsu=OTSU_Segmentation('1.jpg')
otsu.CalTh(256)
otsu.Otsu_translation()

原图及使用OTSU阈值分割后的结果如下:
原图1:
在这里插入图片描述
求得的阈值如下:
在这里插入图片描述
阈值分割结果如下:
在这里插入图片描述
原图2:在这里插入图片描述
对应的阈值如下:
在这里插入图片描述
分割的结果如下:
在这里插入图片描述

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值