1. 程式人生 > >OSTU大津法影象分割

OSTU大津法影象分割

# OSTU影象分割 最大類間方差法,也成大津法OSTU,它是按影象的灰度特性,將影象分成背景和目標2部分。背景和目標之間的類間方差越大,說明構成影象的2部分的差別越大,當部分目標錯分為背景或部分背景錯分為目標都會導致2部 分差別變小。因此,使類間方差最大的分割意味著錯分概率最小。 包括以下幾個步驟 ### 求取影象的灰度直方圖 ```python # 讀取影象 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]) ``` ### 計算全域性最佳閾值 ```python # 初始化閾值 threshold = 0 # 求取灰度值的和 for i in range(256): threshold += i * channel[i] # 計算全域性最佳閾值 threshold = int(threshold / (u * v)) ``` ### 分割影象 ```python # 初始化輸出影象 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 ``` ## 程式碼實現 ```python 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](https://img2020.cnblogs.com/blog/1883891/202101/1883891-20210114220004189-1576889574.png) > 左側為我自己實現的OSTU分割法,右側為OpenCV自帶的OSTU