OSTU影像分割
最大類間方差法,也成大津法OSTU,它是按影像的灰度特性,將影像分成背景和目標2部分。背景和目標之間的類間方差越大,說明構成影像的2部分的差別越大,當部分目標錯分為背景或部分背景錯分為目標都會導致2部
分差別變小。因此,使類間方差最大的分割意味著錯分概率最小。
包括以下幾個步驟
求取影像的灰度直方圖
# 讀取影像
o_img = cv2.imread('source/house.png')
# 灰度化
img = cv2.cvtColor(o_img, cv2.COLOR_BGR2GRAY)
# 獲取圖片的長寬
u, v = img.shape[:2]
# 求取直方圖
channel, bins = np.histogram(img.ravel(), 256, [0, 256])
計算全域性最佳閾值
# 初始化閾值
threshold = 0
# 求取灰度值的和
for i in range(256):
threshold += i * channel[i]
# 計算全域性最佳閾值
threshold = int(threshold / (u * v))
分割影像
# 初始化輸出影像
out = np.zeros((u, v), np.uint8)
for i in range(u):
for j in range(v):
# 如果大於閾值就將其設定為白色,否則就為黑色
if img[i][j] > threshold:
out[i][j] = 255
else:
out[i][j] = 0
程式碼實現
import cv2
import numpy as np
o_img = cv2.imread('source/house.png')
# 灰度化
img = cv2.cvtColor(o_img, cv2.COLOR_BGR2GRAY)
u, v = img.shape[:2]
channel, bins = np.histogram(img.ravel(), 256, [0, 256])
threshold = 0
for i in range(256):
threshold += i * channel[i]
threshold = int(threshold / (u * v))
out = np.zeros((u, v), np.uint8)
for i in range(u):
for j in range(v):
if img[i][j] > threshold:
out[i][j] = 255
else:
out[i][j] = 0
ret, mask_front = cv2.threshold(img, 175, 255, cv2.THRESH_OTSU)
cv2.imshow('OSTU', mask_front)
cv2.imshow('out', out)
cv2.waitKey(0)
cv2.destroyAllWindows()
執行結果
左側為我自己實現的OSTU分割法,右側為OpenCV自帶的OSTU分割。