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()