本文介紹使用不同的閾值方法“二值化”圖像
固定閾值分割
圖解
代碼
import cv2 as cv
# 讀入灰度圖像
img = cv.imread('baby_g.jpg', 0)
# 閾值127分割圖像
ret, th = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
cv.imshow('thresh', th)
cv.waitKey(0)
cv.destroyAllWindows()
函數講解
cv.threshold()用來實現閾值分割,ret是return value縮寫,代表當前的閾值,暫時不用理會。函數有4個參數:
參數1:要處理的原圖,一般是灰度圖
參數2:設定的閾值
參數3:最大閾值,一般為255
參數4:閾值的方式,主要有5種。
cv.threshold() 參數4閾值方式詳解
實驗
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('gradient.jpg',0)
# 應用5種不同的閾值方法
ret, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
ret, th2 = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
ret, th3 = cv.threshold(img, 127, 255, cv.THRESH_TRUNC)
ret, th4 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO)
ret, th5 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO_INV)
titles = ['Original', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, th1, th2, th3, th4, th5]
# 使用Matplotlib顯示
for i in range(6):
plt.subplot(2, 3, i + 1)
plt.imshow(images[i], 'gray')
plt.title(titles[i], fontsize=8)
plt.xticks([]), plt.yticks([]) # 隱藏坐標軸
plt.show()
實驗輸出
官網中的說明
一點說明
很多人誤以為閾值分割就是二值化。從上圖中可以發現,兩者並不等同,閾值分割結果是兩類值,而不是兩個值,所以教程開頭我把二值化加了引號。
自適應閾值
簡介及函數說明
看得出來固定閾值是在整幅圖片上應用一個閾值進行分割,它並不適用於明暗分布不均的圖片。 cv.adaptiveThreshold()自適應閾值會每次取圖片的一小部分計算閾值,這樣圖片不同區域的閾值就不盡相同。它有5個參數:
參數1:要處理的原圖
參數2:最大閾值,一般為255
參數3:小區域閾值的計算方式
ADAPTIVE_THRESH_MEAN_C:小區域內取均值
ADAPTIVE_THRESH_GAUSSIAN_C:小區域內加權求和,權重是個高斯核
參數4:閾值方式(跟前面講的那5種相同)
參數5:小區域的面積,如11就是11*11的小塊
參數6:最終閾值等於小區域計算出的閾值再減去此值
實驗
import cv2 as cv
import matplotlib.pyplot as plt
img = cv.imread('paojie_g.jpg',0)
# 固定閾值
ret, th1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
# 自適應閾值
th2 = cv.adaptiveThreshold(
img, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 15, 4)
th3 = cv.adaptiveThreshold(
img, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 15, 8)
titles = ['Original', 'Global(v = 127)', 'Adaptive Mean', 'Adaptive Gaussian']
images = [img, th1, th2, th3]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i], fontsize=8)
plt.xticks([]), plt.yticks([])
plt.show()
實驗結果
Otsu 閾值
原理及python手動實現
實驗
import cv2 as cv
import numpy as np
# Read image
img = cv.imread("paojie_g.jpg",0)
# Otsu's binarization of Opencv
ret2,th2 = cv.threshold(img,0,255,cv.THRESH_BINARY+cv.THRESH_OTSU)
print("threshold >>", ret2)
# Save result
cv.imwrite("out.jpg", th2)
cv.imshow("result", th2)
cv.waitKey(0)
cv.destroyAllWindows()
實驗結果
都看到這里了,點個贊再走唄。