ALearning(二):自适应阈值获取方法(Ostu方法)

Ostu方法是与1979年由日本学者大津提出,也叫大津法。该方法假设图像分为背景和目标两部分,最佳的阈值应当是使得背景和目标完全分开的图像灰度值,此时背景和目标像素集合内应有着最小的差异。

Ostu原理:https://www.cnblogs.com/funfei/p/6943665.html

python代码如下:

# -*- coding: utf-8 -*-
"""
Created on Sat Jan 12 15:06:23 2019

@author: xingyinGao
"""
import numpy as np
import cv2
import copy

class Isplit(object):
    """
    Ostu自适应阈值获取方法:
    当图像为整型数据时,纯python实现;
    当图像非整型时,调用numpy库实现;
    self.interval为非整型时,阈值选择间隔;
    self.threshold为阈值;
    self.bimg为阈值分割图像;
    self.itas为所有可能阈值评价,为列表元素,第一个元素为可能阈值,第二个为评价结果;
    self.count为计数器;
    调用方式:Is=Isplit(image)
             Is.ostu_main()
    查看阈值分割图像:Is.bimage
    """
    def __init__(self,image,interval=10):
        self.img=copy.deepcopy(image)
        self.interval=interval
        self.threshold=None
        self.bimg=None
        self.itas=[]
        self.count=1
        
    def Ostu_float(self):
        min_value=self.img.min()
        max_value=self.img.max()
        step=int((max_value-min_value)/self.interval)
        ths=[min_value+self.interval*(i+1) for i in range(step-1)]
        length=self.img.shape[0]*self.img.shape[1]
        
        for th in ths:
            print('\r当前进度:%s\%s'%(self.count,len(ths)),end='')
            self.count+=1
            loc0=np.where(self.img<th)
            mu_c0=self.img[loc0].mean()###c0类均值
            loc1=np.where(self.img>=th)
            mu_c1=self.img[loc1].mean()###c1类均值
            
            var_c0=np.var(self.img[loc0])###c0类方差
            var_c1=np.var(self.img[loc1])###c1类方差
            
            w0=len(loc0[0])/length###c0类概率
            w1=len(loc1[0])/length###c1类概率
            
            var_c0_c1=w0*w1*(mu_c0-mu_c1)**2##类间方差
            var_c0_1=var_c0*w0+var_c1*w1##类内方差
            
            self.itas.append([th,var_c0_c1/(var_c0_c1+var_c0_1)])###阈值评价指标
            
        self.threshold=max(self.itas,key=lambda x:x[1])
        self.bimage=(self.img>=self.threshold[0]).astype(int)
        
    def Ostu_int(self):
        
        img_list=list(self.img.reshape(-1))
        length=len(img_list)
        for th in set(img_list):
            print('\r当前进度:%s\%s'%(self.count,len(set(img_list))),end='')
            self.count+=1
            par_c0=[[va,img_list.count(va)] for va in set(img_list) if va<th]
            
            par_c1=[[va,img_list.count(va)] for va in set(img_list) if va>=th]
            if par_c0!=[] and par_c1!=[]:
                w0=sum([co[1] for co in par_c0])/length###c0类概率
                w1=sum([co[1] for co in par_c1])/length###c1类概率
                
                mu_c0=sum([vas[0]*(vas[1]/length) for vas in par_c0])/w0###c0类均值
                mu_c1=sum([vas[0]*(vas[1]/length) for vas in par_c1])/w1###c1类均值
                
                var_c0=sum([((vas[0]-mu_c0)**2)*(vas[1]/length) for vas in par_c0])/w0###c0类方差
                var_c1=sum([((vas[0]-mu_c0)**2)*(vas[1]/length) for vas in par_c1])/w1###c1类方差
                            
                var_c0_c1=w0*w1*(mu_c0-mu_c1)**2##类间方差
                var_c0_1=var_c0*w0+var_c1*w1##类内方差
                
                self.itas.append([th,var_c0_c1/(var_c0_c1+var_c0_1)])###阈值评价指标
        
        self.threshold=max(self.itas,key=lambda x:x[1])
        self.bimage=(self.img>=self.threshold[0]).astype(int)
    
    def ostu_main(self):
        if self.img.ndim==3:
#            self.img=cv2.cvtColor(self.img,cv2.COLOR_RGB2GRAY)
            self.img=(0.2989 *self.img[:,:,0]+0.5870 *self.img[:,:,1]+0.1140*self.img[:,:,2]).astype(self.img.dtype)
        if self.img.dtype!=int:
            self.Ostu_float()
        else:
            self.Ostu_int()

猜你喜欢

转载自blog.csdn.net/zhuzhongzhuo/article/details/86320909