OSTU大津法影像分割

tanknee發表於2021-01-14

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

執行結果

image-20210114215731299

左側為我自己實現的OSTU分割法,右側為OpenCV自帶的OSTU分割。

相關文章