OpenCV+python:图像二值化
1,圖像二值化概念及方法
一個像素點的顏色是由RGB三個值來表現的,所以一個像素點矩陣對應三個顏色向量矩陣,分別是R矩陣,G矩陣,B矩陣,它們也都是同樣大小的矩陣。
在圖像處理中,用RGB三個分量(R:Red,G:Green,B:Blue),即紅、綠、藍三原色來表示真彩色,R分量,G分量,B分量的取值范圍均為0~255,比如電腦屏幕上的一個紅色的像素點的三個分量的值分別為:255,0,0。
在理解了一張圖片是由一個像素點矩陣構成之后,我們就知道我們對圖像的處理就是對這個像素點矩陣的操作,想要改變某個像素點的顏色,我們只要在這個像素點矩陣中找到這個像素點的位置,比如第x行,第y列,所以這個像素點在這個像素點矩陣中的位置就可以表示成(x,y),因為一個像素點的顏色由紅、綠、藍三個顏色變量表示,所以我們通過給這三個變量賦值,來改變這個像素點的顏色,比如改成紅色(255,0,0),可以表示為(x,y,(R=255,G=0,B=0))。
圖像灰度化就是讓像素點矩陣中的每一個像素點都滿足下面的關系:R=G=B(就是紅色變量的值,綠色變量的值,和藍色變量的值,這三個值相等,“=”的意思不是程序語言中的賦值,是數學中的相等),此時的這個值叫做灰度值
二值化就是讓圖像的像素點矩陣中的每個像素點的灰度值為0(黑色)或者255(白色),也就是讓整個圖像呈現只有黑和白的效果。在灰度化的圖像中灰度值的范圍為0~255,在二值化后的圖像中的灰度值范圍是0或者255。
常用簡單的二值化方法(還有很多):
方法1:
取閥值為127(相當于0~255的中數,(0+255)/2=127),讓灰度值小于等于127的變 為0(黑色),灰度值大于127的變為255(白色),這樣做的好處是計算量小速度快,但是 缺點也是很明顯的,因為這個閥值在不同的圖片中均為127,但是不同的圖片,他們的顏色 分布差別很大,所以用127做閥值,白菜蘿卜一刀切,效果肯定是不好的。
方法2:
計算像素點矩陣中的所有像素點的灰度值的平均值avg
(像素點1灰度值+…+像素點n灰度值)/ n = 像素點平均值avg
然后讓每一個像素點與avg一 一比較,小于等于avg的像素點就為0(黑色),大于avg的 像 素點為255(白色),這樣做比方法1好一些。
方法3:
使用直方圖方法(也叫雙峰法)來尋找二值化閥值,直方圖是圖像的重要特質。直方圖方法 認為圖像由前景和背景組成,在灰度直方圖上,前景和背景都形成高峰,在雙峰之間的最低 谷處就是閥值所在。取到閥值之后再一 一比較就可以了。
2,圖像二值化代碼實現
利用OpenCV的API進行二值化處理源代碼:
import cv2 as cv
import numpy as npdef threshold_demo(image): #全局閾值gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)ret, binary = cv.threshold(gray, 127, 255, cv.THRESH_BINARY|cv.THRESH_OTSU)print("threshold value %s"%ret)cv.imshow("global_threshold_binary", binary)
"""cv2.threshold函數是有兩個返回值的,第一個返回值,得到圖像的閾值,第二個返回值,也就是閾值處理后的圖像,我們自己不一定能夠找到一個最好的閾值,去二分化圖像,所以我們需要算法自己去尋找一個閾值,而cv.THRESH_OTSU就可以滿足這個需求,去找到一個最好的閾值。注意:他非常適用于圖像灰度直方圖具有雙峰的情況,他會在雙峰之間找到一個值作為閾值,對于非雙峰圖像,可能并不是很好用。因為cv.THRESH_OTSU方法會產生一個閾值,那么函數cv2.threshold的的第二個參數(設置閾值)就是0(None)了,并且在cv2.threshold的方法參數中還得加上語句cv2.THRESH_OTSU這里面第三個參數maxval參數表示與THRESH_BINARY和THRESH_BINARY_INV閾值類型一起使用設置的最大值。而我們使用的灰度圖像最大則為255,所以設置為255即可THRESH_OTSU最適用于雙波峰 THRESH_TRIANGLE最適用于單個波峰,最開始用于醫學分割細胞等"""def local_threshold(image): #局部閾值gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)binary = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 25, 10)cv.imshow("local_threshold_binary", binary)
"""
函數原型為:adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) -> dstsrc參數表示輸入圖像(8位單通道圖像)。maxValue參數表示使用 THRESH_BINARY 和 THRESH_BINARY_INV 的最大值.adaptiveMethod參數表示自適應閾值算法,平均 (ADAPTIVE_THRESH_MEAN_C)或高斯(ADAPTIVE_THRESH_GAUSSIAN_C)。thresholdType參數表示閾值類型,必須為THRESH_BINARY或THRESH_BINARY_INV的閾值類型。blockSize參數表示塊大小(奇數且大于1,比如3,5,7........ )。C參數是常數,表示從平均值或加權平均值中減去的數。 通常情況下,這是正值,但也可能為零或負值。在使用平均和高斯兩種算法情況下,通過計算每個像素周圍blockSize x blockSize大小像素塊的加權均值并減去常量C即可得到自適應閾值。如果使用平均的方法,則所有像素周圍的權值相同;如果使用高斯的方法,則每個像素周圍像素的權值則根據其到中心點的距離通過高斯方程得到。
"""def custom_threshold(image): #自定義閾值gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)h, w = gray.shape[:2]m = np.reshape(gray, [1, w*h]) #降維mean = m.sum() / (w*h) #求均值# print("mean : ", mean)ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)#利用均值進行圖像二值化cv.imshow("custom_threshold_binary", binary)src = cv.imread("F:/images/text1.png")
cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("input image", src)
threshold_demo(src)
local_threshold(src)
custom_threshold(src)cv.waitKey(0)cv.destroyAllWindows()
運行結果:
3,超大圖像二值化
對于超大圖像,一般要先分塊然后再局部二值化(方便顯示和進一步后處理):
源代碼:
import cv2 as cv
import numpy as npdef big_image_binary(image):print(image.shape)#查看圖像大小cw = 256 #定義塊的大小ch = 256h, w = image.shape[:2]gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)for row in range(0, h, ch):for col in range(0, w, cw):roi = gray[row:row+ch, col:cw+col]#dst = cv.adaptiveThreshold(roi, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY ,127,20)噪聲比較多時采用自適應方法比較好print(np.std(roi), np.mean(roi))dev = np.std(roi)#針對空白圖像,不處理,可以提高效率或者去噪if dev < 15:gray[row:row + ch, col:cw + col] = 255else:ret, dst = cv.threshold(roi, 0, 255, | cv.THRESH_OTSU)gray[row:row + ch, col:cw + col] = dstcv.imwrite("D:/vcprojects/result_binary.png", gray)src = cv.imread("F:/images/red_text.png")
#cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
#cv.imshow("input image", src)
big_image_binary(src)
cv.waitKey(0)cv.destroyAllWindows()
總結
以上是生活随笔為你收集整理的OpenCV+python:图像二值化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 看了一年级,发现小宋佳真是漂亮,就不知道
- 下一篇: OpenCV+python:图像金字塔