OTSU算法是由日本学者大津于1979年提出的一种对图像进行二值化的高效算法。具体原理优快云上一大堆,在此不再赘述,直接上自己写的源代码之前先说一下本人的算法步骤:
(1)读入一幅图像;
(2)将读入的图像灰度化;
(3)将灰度图中各灰度级个数进行统计;
(4)统计各灰度级个数占图像的比例;
(5)遍历灰度级,根据公式求最大类间方差;
(6)最大类间方差对应的灰度级即为阈值,根据阈值对图像进行二值化划分。
Python+OpenCV代码如下:
import cv2 as cv
import numpy as np
def rgb2gray(img):
h=img.shape[0]
w=img.shape[1]
img1=np.zeros((h,w),np.uint8)
for i in range(h):
for j in range(w):
img1[i,j]=0.144*img[i,j,0]+0.587*img[i,j,1]+0.299*img[i,j,1]
return img1
def otsu(img):
h=img.shape[0]
w=img.shape[1]
m=h*w # 图像像素点总和
otsuimg=np.zeros((h,w),np.uint8)
threshold_max=threshold=0 # 定义临时阈值和最终阈值
histogram=np.zeros(256,np.int32) # 初始化各灰度级个数统计参数
probability=np.zeros(256,np.float32) # 初始化各灰度级占图像中的分布的统计参数
for i in range (h):
for j in range (w):
s=img[i,j]
histogram[s]+=1 # 统计像素中每个灰度级在整幅图像中的个数
for k in range (256):
probability[k]=histogram[k]/m # 统计每个灰度级个数占图像中的比例
for i in range (255):
w0 = w1 = 0 # 定义前景像素点和背景像素点灰度级占图像中的分布
fgs = bgs = 0 # 定义前景像素点灰度级总和and背景像素点灰度级总和
for j in range (256):
if j<=i: # 当前i为分割阈值
w0+=probability[j] # 前景像素点占整幅图像的比例累加
fgs+=j*probability[j]
else:
w1+=probability[j] # 背景像素点占整幅图像的比例累加
bgs+=j*probability[j]
u0=fgs/w0 # 前景像素点的平均灰度
u1=bgs/w1 # 背景像素点的平均灰度
g=w0*w1*(u0-u1)**2 # 类间方差
if g>=threshold_max:
threshold_max=g
threshold=i
print(threshold)
for i in range (h):
for j in range (w):
if img[i,j]>threshold:
otsuimg[i,j]=255
else:
otsuimg[i,j]=0
return otsuimg
image = cv.imread("D:/selina.png")
grayimage = rgb2gray(image)
otsuimage = otsu(grayimage)
cv.imshow("image", image)
cv.imshow("grayimage",grayimage)
cv.imshow("otsu", otsuimage)
cv.waitKey(0)
cv.destroyAllWindows()
实验结果:
以上就是大津法全过程,也算是数字图像处理中的基础算法之一,有关大津法的改进优快云上也有好多,本人实现的也只是最基本的。