二值化黑白影像
這篇教學會介紹如何運用 OpenCV 裡的 threshold() 方法,將影像上轉換為二值化的黑白影像,進一步使用 adaptiveThreshold() 自適應二值化的方法,產生效果更好的黑白影像。
快速導覽:
什麼是二值化 ( 閾值二進制 )?
threshold() 產生黑白影像
adaptiveThreshold() 自適應二值化
影片的二值化黑白效果
因為程式中的 OpenCV 會需要使用鏡頭或 GPU,所以請
使用本機環境
( 參考:
使用 Python 虛擬環境
) 或
使用 Anaconda Jupyter 進行實作
( 參考:
使用 Anaconda
) ,並
安裝 OpenCV 函式庫
( 參考:
OpenCV 函式庫
)。
什麼是二值化 ( 閾值二進制 )?
二值化又稱為「閾值二進制」( 閾發音 ㄩ、 ),是一種簡單的圖像分割方法,二值化會根據「閾值」( 類似臨界值 ) 進行轉換,
例如某個像素的灰度值大於閾值,則轉換為黑色,如果這個像素的灰度小於閾值則轉換為白色,進而實現二值化的轉換效果
,經過二值化轉換的圖片,通常只會剩下黑和白兩個值。
許多影像辨識或影像處理的領域 ( 例如輪廓偵測、邊緣偵測...等 ),都會使用二值化影像進行運算,有些影像處理甚至會先將圖片二值化後,再進行後續的計算處理。
threshold() 方法可以
將灰階的影像,以二值化的方式轉換成黑白影像
,使用方法如下:
ret, output = cv2.THRESH_BINARY(img, thresh, maxval, type)
# ret 是否成功轉換,成功 True,失敗 False
# img 來源影像
# thresh 閾值,通常設定 127
# maxval 最大灰度,通常設定 255
# type 轉換方式
threshold() 方法有下列幾種轉換方式,使用 127 和 255 作為說明範例 ( 參考
cv::ThresholdTypes
):
cv2.THRESH_BINARY
如果大於 127 就等於 255,反之等於 0。
cv2.THRESH_BINARY_INV
如果大於 127 就等於 0,反之等於 255。
cv2.THRESH_TRUNC
如果大於 127 就等於 127,反之數值不變。
cv2.THRESH_TOZERO
如果大於 127 數值不變,反之數值等於 0。
cv2.THRESH_TOZERO_INV
如果大於 127 等於 0,反之數值不變。
下方的程式執行後,會將一張黑白漸層的圖片,根據不同的轉換方式,轉換成二值化的黑白圖片 ( 注意,轉換前都要先將圖片轉換成灰階色彩 )。
範例圖片:
下載連結
import cv2
img = cv2.imread('gradient.png')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY); # 轉換前,都先將圖片轉換成灰階色彩
ret, output1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY) # 如果大於 127 就等於 255,反之等於 0。
ret, output2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV) # 如果大於 127 就等於 0,反之等於 255。
ret, output3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC) # 如果大於 127 就等於 127,反之數值不變。
ret, output4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO) # 如果大於 127 數值不變,反之數值等於 0。
ret, output5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV) # 如果大於 127 等於 0,反之數值不變。
cv2.imshow('oxxostudio', img)
cv2.imshow('oxxostudio1', output1)
cv2.imshow('oxxostudio2', output2)
cv2.imshow('oxxostudio3', output3)
cv2.imshow('oxxostudio4', output4)
cv2.imshow('oxxostudio5', output5)
cv2.waitKey(0) # 按下任意鍵停止
cv2.destroyAllWindows()
adaptiveThreshold() 自適應二值化
使用 threshold() 方法轉換灰階的影像時,必須手動設定灰度和閾值,比較適合內容較單純的影像,如果遇到內容比較複雜的影像,每個像素間可能都有關連性,這時就可以使用 adaptiveThreshold() 方法,進行自適應二值化的轉換,自適應二值化可以根據指定大小的區域平均值,或是整體影像的高斯平均值,判斷所需的灰度和閾值,進而產生更好的轉換效果。
adaptiveThreshold() 的使用方法如下:
cv2.adaptiveThreshold(img, maxValue, adaptiveMethod, thresholdType, blockSize, C)
# img 來源影像
# maxValue 最大灰度,通常設定 255
# adaptiveMethod 自適應二值化計算方法
# thresholdType 二值化轉換方式
# blockSize 轉換區域大小,通常設定 11
# C 偏移量,通常設定 2
使用時 thresholdType 為二值化轉換方式,可以參考上方轉換方式列表,adaptiveMethod 自適應二值化計算方法有兩種,分別是:
自適應二值化方法
cv2.ADAPTIVE_THRESH_MEAN_C
使用區域平均值。
cv2.ADAPTIVE_THRESH_GAUSSIAN_C
使用整體高斯平均值。
下方的程式執行後,會將一張數獨的照片,根據不同的自適應二值化轉換方式,轉換成黑白圖片 ( 注意,轉換前都要先將圖片轉換成灰階色彩 )。
範例圖片:下載連結
import cv2
img = cv2.imread('test.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY); # 轉換前,都先將圖片轉換成灰階色彩
ret, output1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
output2 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2)
output3 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
cv2.imshow('oxxostudio', img)
cv2.imshow('oxxostudio1', output1)
cv2.imshow('oxxostudio2', output2)
cv2.imshow('oxxostudio3', output3)
cv2.waitKey(0)
cv2.destroyAllWindows()
如果要降低圖片的雜訊,可以使用 cv2.medianBlur() 先將圖片模糊化,下方的範例可以看見有模糊化和沒有模糊化的差異:
參考:影像模糊化
import cv2
img = cv2.imread('test.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);
output1 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
img_gray2 = cv2.medianBlur(img_gray, 5) # 模糊化
output2 = cv2.adaptiveThreshold(img_gray2, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
cv2.imshow('oxxostudio1', output1)
cv2.imshow('oxxostudio2', output2)
cv2.waitKey(0)
cv2.destroyAllWindows()
延伸「讀取並播放影片」文章的範例,在程式碼中使用自適應二值化方法,就能將電腦鏡頭拍攝的畫面,即時轉換成二值化黑白的影像。
import cv2
cap = cv2.VideoCapture(0)
if not cap.isOpened():
print("Cannot open camera")
exit()
while True:
ret, frame = cap.read()
if not ret:
print("Cannot receive frame")
break
# 套用自適應二值化黑白影像
img_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY);
img_gray = cv2.medianBlur(img_gray, 5)
output = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
cv2.imshow('oxxostudio', output)
if cv2.waitKey(1) == ord('q'):
break # 按下 q 鍵停止
cap.release()
cv2.destroyAllWindows()
https://docs.opencv.org/4.x/d7/d4d/tutorial_py_thresholding.html
如果有任何建議或問題,可傳送「」給我,謝謝~
Python 學習導讀
關於 Python
使用 Google Colab
使用 Anaconda
使用 Python 虛擬環境
Python 範例集錦
變數 variable
變數 ( 全域、區域 )
數字 number
文字與字串 string
文字與字串 ( 常用方法 )
文字與字串 ( 格式化 )
串列 list
串列 ( 常用方法 )
元組/數組 tuple
字典 dictionary
集合 set
縮排和註解
運算子 operator
邏輯判斷 ( if、elif、else )
邏輯判斷 ( and 和 or )
重複迴圈 ( for、while )
例外處理 ( try、except )
生成式 comprehension
物件類別 class
物件繼承 inheritance
匯入模組 import
函式 function
匿名函式 lambda
遞迴 recursion
產生器 generator
裝飾器 decorator
閉包 closure
內建函式&方法
輸入與輸出
字串操作與轉換
迭代物件轉換
迭代物件操作
檔案讀寫 ( open )
eval() 與 exec()
標準函式庫&模組
隨機數 random
數學 math
數學統計函式 statistics
時間與日期 datetime
時間處理 time
日曆 calendar
使用正規表達式 re
檔案操作 os
查找匹配檔案 glob
壓縮檔案 zipfile
高階檔案操作 shutil
高效迭代器 itertools
容器資料型態 collections
CSV 檔案操作
JSON 檔案操作
threading 多執行緒處理
concurrent.futures