二值化黑白图像
这篇教学会介绍如何运用 OpenCV 里的 threshold() 方法,将图像上转换为二值化的黑白图像,进一步使用 adaptiveThreshold() 自适应二值化的方法,产生效果更好的黑白图像。
快速导览:
因为程序中的 OpenCV 会需要使用镜头或 GPU,所以请使用本机环境 ( 参考:使用 Python 虚拟环境 ) 或使用 Anaconda Jupyter 进行实作 ( 参考:使用 Anaconda ) ,并安装 OpenCV 函数库 ( 参考:OpenCV 函数库 )。
什么是二值化 ( 阈值二进制 )?
二值化又称为“阈值二进制”( 阈发音 ㄩ、 ),是一种简单的图像分割方法,二值化会根据“阈值”( 类似临界值 ) 进行转换,例如某个像素的灰度值大于阈值,则转换为黑色,如果这个像素的灰度小于阈值则转换为白色,进而实现二值化的转换效果,经过二值化转换的图片,通常只会剩下黑和白两个值。
许多图像辨识或图像处理的领域 ( 例如轮廓侦测、边缘侦测...等 ),都会使用二值化图像进行运算,有些图像处理甚至会先将图片二值化后,再进行后续的计算处理。
threshold() 产生黑白图像
threshold() 方法可以将灰阶的图像,以二值化的方式转换成黑白图像,使用方法如下:
ret, output = cv2.threshold(img, thresh, maxval, type)
# ret 是否成功轉換,成功會顯示閾值
# output 轉換後的影像
# 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()
微信扫码关注
抖音扫码关注