OSTU大津法影象分割
阿新 • • 發佈:2021-01-15
# 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