從彩色變灰階
使用 cv.cvtColor()函數可作色彩的空間轉換,例如要偵測顏色時,要轉成HSV
1 | imageHSV = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) |
而降為灰階則為
1 | imageHSV = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) |
從灰階到黑白
要把圖片從灰階變成黑白很簡單。對於每個像素,應用相同的閾值。如果像素值小於閾值,則設置為0,否則設置為最大值。函數cv.threshold用於應用閾值。第一個參數是源圖像,應該是灰度圖像。第二個參數是用於對像素值進行分類的閾值。第三個參數是分配給超過閾值的像素值的最大值。
可使用參數cv.threshold
和cv.adaptiveThreshold
。
cv.threshold
使用範例
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 | import cv2 as cv import numpy as np from matplotlib import pyplot as plt img = cv.imread( 'gradient.png' , 0 ) ret,thresh1 = cv.threshold(img, 127 , 255 ,cv.THRESH_BINARY) ret,thresh2 = cv.threshold(img, 127 , 255 ,cv.THRESH_BINARY_INV) ret,thresh3 = cv.threshold(img, 127 , 255 ,cv.THRESH_TRUNC) ret,thresh4 = cv.threshold(img, 127 , 255 ,cv.THRESH_TOZERO) ret,thresh5 = cv.threshold(img, 127 , 255 ,cv.THRESH_TOZERO_INV) titles = [ 'Original Image' , 'BINARY' , 'BINARY_INV' , 'TRUNC' , 'TOZERO' , 'TOZERO_INV' ] images = [img, thresh1, thresh2, thresh3, thresh4, thresh5] for i in range ( 6 ): plt.subplot( 2 , 3 ,i + 1 ),plt.imshow(images[i], 'gray' ,vmin = 0 ,vmax = 255 ) plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show() |
cv.adaptiveThreshold
在cv.threshold使用一個全局值作為閾值。但這可能並不適用於所有情況,例如,如果圖像在不同區域具有不同的光照條件。在這種情況下,自適應閾值可以提供幫助。在這裡,算法根據像素周圍的小區域確定像素的閾值。因此,我們為同一圖像的不同區域獲得不同的閾值,這為具有不同光照的圖像提供了更好的結果。
除了上述參數外,方法cv.adaptiveThreshold 還需要三個輸入參數:
adaptiveMethod決定如何計算閾值:
- cv.ADAPTIVE_THRESH_MEAN_C:閾值是鄰域面積的平均值減去常量C。
- cv.ADAPTIVE_THRESH_GAUSSIAN_C :閾值是鄰域值減去常量C的高斯加權和。
- blockSize確定鄰域區域的大小,C是從鄰域像素的平均值或加權總和中減去的常數。
下面比較了具有不同光照的圖像的全局閾值和自適應閾值:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | import cv2 as cv import numpy as np from matplotlib import pyplot as plt img = cv.imread( 'sudoku.png' , 0 ) img = cv.medianBlur(img, 5 ) ret,th1 = cv.threshold(img, 127 , 255 ,cv.THRESH_BINARY) th2 = cv.adaptiveThreshold(img, 255 ,cv.ADAPTIVE_THRESH_MEAN_C,\ cv.THRESH_BINARY, 11 , 2 ) th3 = cv.adaptiveThreshold(img, 255 ,cv.ADAPTIVE_THRESH_GAUSSIAN_C,\ cv.THRESH_BINARY, 11 , 2 ) titles = [ 'Original Image' , 'Global Thresholding (v = 127)' , 'Adaptive Mean Thresholding' , 'Adaptive Gaussian Thresholding' ] 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]) plt.xticks([]),plt.yticks([]) plt.show() |
cv.threshold使用THRESH_OTSU
在全局閾值中,使用任意選擇的值作為閾值。相反,Otsu 的方法避免了必須選擇一個值並自動確定它。
考慮只有兩個不同圖像值的圖像(雙峰圖像),其中直方圖僅包含兩個峰值。一個好的閾值應該在這兩個值的中間。類似地,Otsu 的方法從圖像直方圖中確定最佳全局閾值。
為此,使用了cv.threshold()函數,其中cv.THRESH_OTSU作為額外標誌傳遞。閾值可以任意選擇。然後算法找到最佳閾值,該閾值作為第一個輸出返回。
查看下面的示例。輸入圖像是有噪聲的圖像。在第一種情況下,應用值為 127 的全局閾值。在第二種情況下,直接應用 Otsu 的閾值。在第三種情況下,首先使用 5×5 高斯核對圖像進行濾波以去除噪聲,然後應用 Otsu 閾值處理。查看噪聲過濾如何改善結果。
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | import cv2 as cv import numpy as np from matplotlib import pyplot as plt img = cv.imread( 'noisy2.png' , 0 ) # global thresholding ret1,th1 = cv.threshold(img, 127 , 255 ,cv.THRESH_BINARY) # Otsu's thresholding ret2,th2 = cv.threshold(img, 0 , 255 ,cv.THRESH_BINARY + cv.THRESH_OTSU) # Otsu's thresholding after Gaussian filtering blur = cv.GaussianBlur(img,( 5 , 5 ), 0 ) ret3,th3 = cv.threshold(blur, 0 , 255 ,cv.THRESH_BINARY + cv.THRESH_OTSU) # plot all the images and their histograms images = [img, 0 , th1, img, 0 , th2, blur, 0 , th3] titles = [ 'Original Noisy Image' , 'Histogram' , 'Global Thresholding (v=127)' , 'Original Noisy Image' , 'Histogram' , "Otsu's Thresholding" , 'Gaussian filtered Image' , 'Histogram' , "Otsu's Thresholding" ] for i in range ( 3 ): plt.subplot( 3 , 3 ,i * 3 + 1 ),plt.imshow(images[i * 3 ], 'gray' ) plt.title(titles[i * 3 ]), plt.xticks([]), plt.yticks([]) plt.subplot( 3 , 3 ,i * 3 + 2 ),plt.hist(images[i * 3 ].ravel(), 256 ) plt.title(titles[i * 3 + 1 ]), plt.xticks([]), plt.yticks([]) plt.subplot( 3 , 3 ,i * 3 + 3 ),plt.imshow(images[i * 3 + 2 ], 'gray' ) plt.title(titles[i * 3 + 2 ]), plt.xticks([]), plt.yticks([]) plt.show() |