該系列文章是講解Python OpenCV圖像處理知識,前期主要講解圖像入門、OpenCV基礎用法,中期講解圖像處理的各類算法,包括圖像銳化算子、圖像加強技術、圖像分割等,後期結合深度學習研究圖像識別、圖像分類應用。但願文章對您有所幫助,若是有不足之處,還請海涵~python
前面一篇文章介紹了圖像量化及採樣處理,這篇文章將結合做者研究民族服飾及文化圖騰識別,詳細講解圖像點運算,包括灰度化處理、灰度線性變換、灰度非線性變換、閾值化處理,萬字長文吐血整理,但願對您有所幫助。同時,該部分知識均爲做者查閱資料撰寫總結,而且開設成了收費專欄,爲小寶賺點奶粉錢,感謝您的擡愛。固然若是您是在讀學生或經濟拮据,能夠私聊我給你每篇文章開白名單,或者轉發原文給你,更但願您能進步,一塊兒加油喔~git
該系列在github全部源代碼:github
前文參考:
[Python圖像處理] 一.圖像處理基礎知識及OpenCV入門函數
[Python圖像處理] 二.OpenCV+Numpy庫讀取與修改像素
[Python圖像處理] 三.獲取圖像屬性、興趣ROI區域及通道處理
[Python圖像處理] 四.圖像平滑之均值濾波、方框濾波、高斯濾波及中值濾波
[Python圖像處理] 五.圖像融合、加法運算及圖像類型轉換
[Python圖像處理] 六.圖像縮放、圖像旋轉、圖像翻轉與圖像平移
[Python圖像處理] 七.圖像閾值化處理及算法對比
[Python圖像處理] 八.圖像腐蝕與圖像膨脹
[Python圖像處理] 九.形態學之圖像開運算、閉運算、梯度運算
[Python圖像處理] 十.形態學之圖像頂帽運算和黑帽運算
[Python圖像處理] 十一.灰度直方圖概念及OpenCV繪製直方圖
[Python圖像處理] 十二.圖像幾何變換之圖像仿射變換、圖像透視變換和圖像校訂
[Python圖像處理] 十三.基於灰度三維圖的圖像頂帽運算和黑帽運算
[Python圖像處理] 十四.基於OpenCV和像素處理的圖像灰度化處理
[Python圖像處理] 十五.圖像的灰度線性變換
[Python圖像處理] 十六.圖像的灰度非線性變換之對數變換、伽馬變換
[Python圖像處理] 十七.圖像銳化與邊緣檢測之Roberts算子、Prewitt算子、Sobel算子和Laplacian算子
[Python圖像處理] 十八.圖像銳化與邊緣檢測之Scharr算子、Canny算子和LOG算子
[Python圖像處理] 十九.圖像分割之基於K-Means聚類的區域分割
[Python圖像處理] 二十.圖像量化處理和採樣處理及局部馬賽克特效
[Python圖像處理] 二十一.圖像金字塔之圖像向下取樣和向上取樣
[Python圖像處理] 二十二.Python圖像傅里葉變換原理及實現
[Python圖像處理] 二十三.傅里葉變換之高通濾波和低通濾波
[Python圖像處理] 二十四.圖像特效處理之毛玻璃、浮雕和油漆特效
[Python圖像處理] 二十五.圖像特效處理之素描、懷舊、光照、流年以及濾鏡特效
[Python圖像處理] 二十六.圖像分類原理及基於KNN、樸素貝葉斯算法的圖像分類案例
[Python圖像處理] 二十七.OpenGL入門及繪製基本圖形(一)
[Python圖像處理] 二十八.OpenCV快速實現人臉檢測及視頻中的人臉
[Python圖像處理] 二十九.MoviePy視頻編輯庫實現抖音短視頻剪切合並操做
[Python圖像處理] 三十.圖像量化及採樣處理萬字詳細總結(推薦)
算法
文章目錄
圖像的點運算是指對圖像中的每一個像素依次進行灰度變換的運算,主要用於改變一幅圖像的灰度分佈範圍,經過必定的變換函數將圖像的灰度值進行轉換,生成新的圖像的過程。點運算是圖像處理中的基礎技術,常見的包括灰度化處理、灰度線性變換、灰度非線性變換、閾值化處理等。編程
一.圖像點運算的概述
圖像點運算(Point Operation)指對於一幅輸入圖像,將產生一幅輸出圖像,輸出圖像的每一個像素點的灰度值由輸入像素點決定。點運算其實是灰度到灰度的映射過程,經過映射變換來達到加強或者減弱圖像的灰度。還能夠對圖像進行求灰度直方圖、線性變換、非線性變換以及圖像骨架的提取。它與相鄰的像素之間沒有運算關係,是一種簡單和有效的圖像處理方法。數組
它在實際中有不少的應用:安全
- 光度學標定(Photometric Calibration):但願數字圖像的灰度可以真實反映圖像的物理特性。好比:去掉非線性、變換灰度的單位。
- 對比度加強(Contrast Enhancement)或對比度擴展(Contrast stretching):將感興趣特徵的對比度擴展,讓其佔據灰度級的更大部分。
- 顯示標定(Display Calibration):顯示設備不能線性地將灰度值轉化爲光強度。所以點運算和顯示非線性結合,以保持顯示圖像時的線性關係。
- 輪廓線肯定:用點運算的方式進行閾值化。
設輸入圖像爲A(x,y),輸出圖像爲B(x,y),則點運算能夠表示爲:網絡
B ( x , y ) = f [ A ( x , y ) ] B(x,y) = f[A(x,y)] B(x,y)=f[A(x,y)]函數
從中能夠看出:學習
- 與幾何運算的差異,不會改變圖像內像素點之間的空間位置關係。
- 與局部(領域)運算的差異,輸入像素-輸出像素一一對應。
- 又稱爲對比度加強、對比度拉伸或灰度變換。
圖像的灰度變換能夠經過有選擇的突出圖像感興趣的特徵或者抑制圖像中不須要的特徵,從而改善圖像的質量,凸顯圖像的細節,提升圖像的對比度。它也能有效地改變圖像的直方圖分佈,使圖像的像素值分佈更爲均勻。
二.圖像灰度化處理
圖像灰度化是將一幅彩色圖像轉換爲灰度化圖像的過程。彩色圖像一般包括R、G、B三個份量,分別顯示出紅綠藍等各類顏色,灰度化就是使彩色圖像的R、G、B三個份量相等的過程。灰度圖像中每一個像素僅具備一種樣本顏色,其灰度是位於黑色與白色之間的多級色彩深度,灰度值大的像素點比較亮,反之比較暗,像素值最大爲255(表示白色),像素值最小爲0(表示黑色)。
假設某點的顏色由RGB(R,G,B)組成,常見灰度處理算法如表1所示:
表1中Gray表示灰度處理以後的顏色,而後將原始RGB(R,G,B)顏色均勻地替換成新顏色RGB(Gray,Gray,Gray),從而將彩色圖片轉化爲灰度圖像。一種常見的方法是將RGB三個份量求和再取平均值,但更爲準確的方法是設置不一樣的權重,將RGB份量按不一樣的比例進行灰度劃分。好比人類的眼睛感官藍色的敏感度最低,敏感最高的是綠色,所以將RGB按照0.29九、0.58七、0.144比例加權平均能獲得較合理的灰度圖像,如公式2所示。
1.基於OpenCV的圖像灰度化處理
在平常生活中,咱們看到的大多數彩色圖像都是RGB類型,可是在圖像處理過程當中,經常須要用到灰度圖像、二值圖像、HSV、HSI等顏色,OpenCV提供了cvtColor()函數實現這些功能。其函數原型以下所示:
- dst = cv2.cvtColor(src, code[, dst[, dstCn]])
– src表示輸入圖像,須要進行顏色空間變換的原圖像
– dst表示輸出圖像,其大小和深度與src一致
– code表示轉換的代碼或標識
– dstCn表示目標圖像通道數,其值爲0時,則有src和code決定
該函數的做用是將一個圖像從一個顏色空間轉換到另外一個顏色空間,其中,RGB是指Red、Green和Blue,一副圖像由這三個通道(channel)構成;Gray表示只有灰度值一個通道;HSV包含Hue(色調)、Saturation(飽和度)和Value(亮度)三個通道。在OpenCV中,常見的顏色空間轉換標識包括CV_BGR2BGRA、CV_RGB2GRAY、CV_GRAY2RGB、CV_BGR2HSV、CV_BGR2XYZ、CV_BGR2HLS等。下面是調用cvtColor()函數將圖像進行灰度化處理的代碼。
# -*- coding: utf-8 -*- # By:Eastmount CSDN 2020-11-12 #encoding:utf-8 import cv2 import numpy as np #讀取原始圖片 src = cv2.imread('miao.png') #圖像灰度化處理 grayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) #顯示圖像 cv2.imshow("src", src) cv2.imshow("result", grayImage) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
輸出結果如圖1所示,左邊是彩色的苗族服飾原圖,右邊是將彩色圖像進行灰度化處理以後的灰度圖。其中,灰度圖將一個像素點的三個顏色變量設置爲至關,R=G=B,此時該值稱爲灰度值。
一樣,能夠調用 grayImage = cv2.cvtColor(src, cv2.COLOR_BGR2HSV) 核心代碼將彩色圖像轉換爲HSV顏色空間,如圖2所示。
下面代碼對比了九種常見的顏色空間,包括BGR、RGB、GRAY、HSV、YCrCb、HLS、XYZ、LAB和YUV,並循環顯示處理後的圖像。
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img_BGR = cv2.imread('miao.png') #BGR轉換爲RGB img_RGB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2RGB) #灰度化處理 img_GRAY = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2GRAY) #BGR轉HSV img_HSV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HSV) #BGR轉YCrCb img_YCrCb = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YCrCb) #BGR轉HLS img_HLS = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2HLS) #BGR轉XYZ img_XYZ = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2XYZ) #BGR轉LAB img_LAB = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2LAB) #BGR轉YUV img_YUV = cv2.cvtColor(img_BGR, cv2.COLOR_BGR2YUV) #調用matplotlib顯示處理結果 titles = ['BGR', 'RGB', 'GRAY', 'HSV', 'YCrCb', 'HLS', 'XYZ', 'LAB', 'YUV'] images = [img_BGR, img_RGB, img_GRAY, img_HSV, img_YCrCb, img_HLS, img_XYZ, img_LAB, img_YUV] for i in range(9): plt.subplot(3, 3, i+1), plt.imshow(images[i], 'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
其運行結果如圖3所示,它是圖像九種顏色空間相互轉換。
2.基於像素操做的圖像灰度化處理
前面講述了調用OpenCV中cvtColor()函數實現圖像灰度化的處理,接下來說解基於像素操做的圖像灰度化處理方法,主要是最大值灰度處理、平均灰度處理和加權平均灰度處理方法。
(1)最大值灰度處理方法
該方法的灰度值等於彩色圖像R、G、B三個份量中的最大值,公式以下:
其方法灰度化處理後的灰度圖亮度很高,實現代碼以下。
# -*- coding: utf-8 -*- #By:Eastmount CSDN 2020-11-12 #encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('miao.png') #獲取圖像高度和寬度 height = img.shape[0] width = img.shape[1] #建立一幅圖像 grayimg = np.zeros((height, width, 3), np.uint8) #圖像最大值灰度處理 for i in range(height): for j in range(width): #獲取圖像R G B最大值 gray = max(img[i,j][0], img[i,j][1], img[i,j][2]) #灰度圖像素賦值 gray=max(R,G,B) grayimg[i,j] = np.uint8(gray) #顯示圖像 cv2.imshow("src", img) cv2.imshow("gray", grayimg) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
圖像最大值灰度處理方法效果輸出結果如圖4所示,其處理效果的灰度偏亮。
(2)平均灰度處理方法
該方法的灰度值等於彩色圖像R、G、B三個份量灰度值的求和平均值,其計算公式如公式(4)所示:
平均灰度處理方法實現代碼以下。
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('miao.png') #獲取圖像高度和寬度 height = img.shape[0] width = img.shape[1] #建立一幅圖像 grayimg = np.zeros((height, width, 3), np.uint8) print grayimg #圖像平均灰度處理方法 for i in range(height): for j in range(width): #灰度值爲RGB三個份量的平均值 gray = (int(img[i,j][0]) + int(img[i,j][1]) + int(img[i,j][2])) / 3 grayimg[i,j] = np.uint8(gray) #顯示圖像 cv2.imshow("src", img) cv2.imshow("gray", grayimg) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
圖像平均灰度處理方法效果輸出結果如圖5所示:
(3)加權平均灰度處理方法
該方法根據色彩重要性,將三個份量以不一樣的權值進行加權平均。因爲人眼對綠色的敏感最高,對藍色敏感最低,所以,按下式對RGB三份量進行加權平均能獲得較合理的灰度圖像。
加權平均灰度處理方法實現代碼以下所示:
#encoding:utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('miao.png') #獲取圖像高度和寬度 height = img.shape[0] width = img.shape[1] #建立一幅圖像 grayimg = np.zeros((height, width, 3), np.uint8) print(grayimg) #圖像平均灰度處理方法 for i in range(height): for j in range(width): #灰度加權平均法 gray = 0.30 * img[i,j][0] + 0.59 * img[i,j][1] + 0.11 * img[i,j][2] grayimg[i,j] = np.uint8(gray) #顯示圖像 cv2.imshow("src", img) cv2.imshow("gray", grayimg) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
圖像加權平均灰度處理方法效果輸出結果如圖6所示:
三.圖像的灰度線性變換
圖像的灰度線性變換是經過創建灰度映射來調整原始圖像的灰度,從而改善圖像的質量,凸顯圖像的細節,提升圖像的對比度。灰度線性變換的計算公式如(6)所示:
該公式中DB表示灰度線性變換後的灰度值,DA表示變換前輸入圖像的灰度值,α和b爲線性變換方程f(D)的參數,分別表示斜率和截距。
- 當α=1,b=0時,保持原始圖像
- 當α=1,b!=0時,圖像全部的灰度值上移或下移
- 當α=-1,b=255時,原始圖像的灰度值反轉
- 當α>1時,輸出圖像的對比度加強
- 當0<α<1時,輸出圖像的對比度減少
- 當α<0時,原始圖像暗區域變亮,亮區域變暗,圖像求補
如圖7所示,顯示了圖像的灰度線性變換對應的效果圖。
1.圖像灰度上移變換
該算法將實現圖像灰度值的上移,從而提高圖像的亮度,其實現代碼以下所示。因爲圖像的灰度值位於0至255區間以內,因此須要對灰度值進行溢出判斷。
D B = D A + 50 D_B=D_A+50 DB=DA+50
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('miao.png') #圖像灰度轉換 grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #獲取圖像高度和寬度 height = grayImage.shape[0] width = grayImage.shape[1] #建立一幅圖像 result = np.zeros((height, width, 3), np.uint8) #圖像灰度上移變換 DB=DA+50 for i in range(height): for j in range(width): if (int(grayImage[i,j]+50) > 255): gray = 255 else: gray = int(grayImage[i,j]+50) result[i,j] = np.uint8(gray) #顯示圖像 cv2.imshow("Gray Image", grayImage) cv2.imshow("Result", result) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
圖像灰度值上移變換輸出結果如圖8所示,圖像的全部灰度值上移50,圖像變得更白了。注意,純黑色對應的灰度值爲0,純白色對應的灰度值爲255。
2.圖像對比度加強變換
該算法將加強圖像的對比度,Python實現代碼以下所示:
D B = D A × 1.5 D_B=D_A×1.5 DB=DA×1.5
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('miao.png') #圖像灰度轉換 grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #獲取圖像高度和寬度 height = grayImage.shape[0] width = grayImage.shape[1] #建立一幅圖像 result = np.zeros((height, width, 3), np.uint8) #圖像對比度加強變換 DB=DA*1.5 for i in range(height): for j in range(width): if (int(grayImage[i,j]*1.5) > 255): gray = 255 else: gray = int(grayImage[i,j]*1.5) result[i,j] = np.uint8(gray) #顯示圖像 cv2.imshow("Gray Image", grayImage) cv2.imshow("Result", result) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
圖像線性對比度加強輸出結果如圖9所示,圖像的全部灰度值加強1.5倍。
3.圖像對比度減弱變換
該算法將減弱圖像的對比度,Python實現代碼以下所示:
D B = D A × 0.8 D_B=D_A×0.8 DB=DA×0.8
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('miao.png') #圖像灰度轉換 grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #獲取圖像高度和寬度 height = grayImage.shape[0] width = grayImage.shape[1] #建立一幅圖像 result = np.zeros((height, width, 3), np.uint8) #圖像對比度減弱變換 DB=DA*0.8 for i in range(height): for j in range(width): gray = int(grayImage[i,j]*0.8) result[i,j] = np.uint8(gray) #顯示圖像 cv2.imshow("Gray Image", grayImage) cv2.imshow("Result", result) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
其輸出結果如圖10所示,圖像的全部灰度值減弱,圖像變得更暗。
4.圖像灰度反色變換
反色變換又稱爲線性灰度求補變換,它是對原圖像的像素值進行反轉,即黑色變爲白色,白色變爲黑色的過程。其Python實現代碼以下所示:
D B = 255 − D A D_B=255-D_A DB=255−DA
#encoding:utf-8 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('miao.png') #圖像灰度轉換 grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #獲取圖像高度和寬度 height = grayImage.shape[0] width = grayImage.shape[1] #建立一幅圖像 result = np.zeros((height, width), np.uint8) #圖像灰度反色變換 DB=255-DA for i in range(height): for j in range(width): gray = 255 - grayImage[i,j] result[i,j] = np.uint8(gray) #顯示圖像 cv2.imshow("Gray Image", grayImage) cv2.imshow("Result", result) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
圖像灰度反色變換輸出結果如圖11所示,圖像處理先後的灰度值是互補的。
圖像灰度反色變換在醫學圖像處理中有必定的應用,如圖12所示:
四.圖像的灰度非線性變換
圖像的灰度非線性變換主要包括對數變換、冪次變換、指數變換、分段函數變換,經過非線性關係對圖像進行灰度處理,下面主要講解三種常見類型的灰度非線性變換。
1.圖像灰度非線性變換:
原始圖像的灰度值按照DB=DA×DA/255的公式進行非線性變換,其代碼以下:
D B = D A × D A / 255 D_B=D_A×D_A/255 DB=DA×DA/255
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取原始圖像 img = cv2.imread('miao.png') #圖像灰度轉換 grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #獲取圖像高度和寬度 height = grayImage.shape[0] width = grayImage.shape[1] #建立一幅圖像 result = np.zeros((height, width), np.uint8) #圖像灰度非線性變換:DB=DA×DA/255 for i in range(height): for j in range(width): gray = int(grayImage[i,j])*int(grayImage[i,j]) / 255 result[i,j] = np.uint8(gray) #顯示圖像 cv2.imshow("Gray Image", grayImage) cv2.imshow("Result", result) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
圖像灰度非線性變換的輸出結果如圖13所示:
2.圖像灰度對數變換
圖像灰度的對數變換通常表示如公式(7)所示:
其中c爲尺度比較常數,DA爲原始圖像灰度值,DB爲變換後的目標灰度值。圖像灰度對數變換如圖14所示,它表示對數曲線下的灰度值變化狀況,其中x表示原始圖像的灰度值,y表示對數變換以後的目標灰度值。
因爲對數曲線在像素值較低的區域斜率大,在像素值較高的區域斜率較小,因此圖像通過對數變換後,較暗區域的對比度將有所提高。這種變換可用於加強圖像的暗部細節,從而用來擴展被壓縮的高值圖像中的較暗像素。
對數變換實現了擴展低灰度值而壓縮高灰度值的效果,被普遍地應用於頻譜圖像的顯示中。一個典型的應用是傅立葉頻譜,其動態範圍可能寬達0~106直接顯示頻譜時,圖像顯示設備的動態範圍每每不能知足要求,從而丟失大量的暗部細節;而在使用對數變換以後,圖像的動態範圍被合理地非線性壓縮,從而能夠清晰地顯示。
在圖15中,未經變換的頻譜通過對數變換後,增長了低灰度區域的對比度,從而加強暗部的細節。下面的代碼實現了圖像灰度的對數變換。
# -*- coding: utf-8 -*- import numpy as np import matplotlib.pyplot as plt import cv2 #繪製曲線 def log_plot(c): x = np.arange(0, 256, 0.01) y = c * np.log(1 + x) plt.plot(x, y, 'r', linewidth=1) plt.rcParams['font.sans-serif']=['SimHei'] #正常顯示中文標籤 plt.title(u'對數變換函數') plt.xlim(0, 255), plt.ylim(0, 255) plt.show() #對數變換 def log(c, img): output = c * np.log(1.0 + img) output = np.uint8(output + 0.5) return output #讀取原始圖像 img = cv2.imread('2016-.png') #繪製對數變換曲線 log_plot(42) #圖像灰度對數變換 output = log(42, img) #顯示圖像 cv2.imshow('Input', img) cv2.imshow('Output', output) cv2.waitKey(0) cv2.destroyAllWindows()
圖16表示通過對數函數處理後的效果圖,對數變換對於總體對比度偏低而且灰度值偏低的圖像加強效果較好。
對應的對數函數曲線如圖17所示,其中x表示原始圖像的灰度值,y表示對數變換以後的目標灰度值。
3.圖像灰度伽瑪變換
伽瑪變換又稱爲指數變換或冪次變換,是另外一種經常使用的灰度非線性變換。圖像灰度的伽瑪變換通常表示如公式(8)所示:
- 當γ>1時,會拉伸圖像中灰度級較高的區域,壓縮灰度級較低的部分。
- 當γ<1時,會拉伸圖像中灰度級較低的區域,壓縮灰度級較高的部分。
- 當γ=1時,該灰度變換是線性的,此時經過線性方式改變原圖像。
Python實現圖像灰度的伽瑪變換代碼以下,主要調用冪函數實現。
#encoding:utf-8 import numpy as np import matplotlib.pyplot as plt import cv2 #繪製曲線 def gamma_plot(c, v): x = np.arange(0, 256, 0.01) y = c*x**v plt.plot(x, y, 'r', linewidth=1) plt.rcParams['font.sans-serif']=['SimHei'] #正常顯示中文標籤 plt.title('伽馬變換函數') plt.xlim([0, 255]), plt.ylim([0, 255]) plt.show() #伽瑪變換 def gamma(img, c, v): lut = np.zeros(256, dtype=np.float32) for i in range(256): lut[i] = c * i ** v output_img = cv2.LUT(img, lut) #像素灰度值的映射 output_img = np.uint8(output_img+0.5) return output_img #讀取原始圖像 img = cv2.imread('2019.png') #繪製伽瑪變換曲線 gamma_plot(0.00000005, 4.0) #圖像灰度伽瑪變換 output = gamma(img, 0.00000005, 4.0) #顯示圖像 cv2.imshow('Imput', img) cv2.imshow('Output', output) cv2.waitKey(0) cv2.destroyAllWindows()
圖18表示通過伽瑪變換處理後的效果圖,伽馬變換對於圖像對比度偏低,而且總體亮度值偏高(或因爲相機過曝)狀況下的圖像加強效果明顯。
對應的伽馬變換曲線如圖19所示,其中x表示原始圖像的灰度值,y表示伽馬變換以後的目標灰度值。
五.圖像閾值化處理
圖像閾值化(Binarization)旨在剔除掉圖像中一些低於或高於必定值的像素,從而提取圖像中的物體,將圖像的背景和噪聲區分開來。圖像閾值化能夠理解爲一個簡單的圖像分割操做,閾值又稱爲臨界值,它的目的是肯定出一個範圍,而後這個範圍內的像素點使用同一種方法處理,而閾值以外的部分則使用另外一種處理方法或保持原樣。
灰度化處理後的圖像中,每一個像素都只有一個灰度值,其大小表示明暗程度。閾值化處理能夠將圖像中的像素劃分爲兩類顏色,常見的閾值化算法如公式(9)所示:
當某個像素點的灰度Gray(i,j)小於閾值T時,其像素設置爲0,表示黑色;當灰度Gray(i,j)大於或等於閾值T時,其像素值爲255,表示白色。在Python的OpenCV庫中,提供了固定閾值化函數threshold()和自適應閾值化函數adaptiveThreshold(),將一幅圖像進行閾值化處理。
1.固定閾值化處理
OpenCV中提供了函數threshold()實現固定閾值化處理,其函數原型以下:
- dst = cv2.threshold(src, thresh, maxval, type[, dst])
– src表示輸入圖像的數組,8位或32位浮點類型的多通道數
– dst表示輸出的閾值化處理後的圖像,其類型和通道數與src一致
– thresh表示閾值
– maxval表示最大值,當參數閾值類型type選擇CV_THRESH_BINARY或CV_THRESH_BINARY_INV時,該參數爲閾值類型的最大值
– type表示閾值類型
其中,圖像閾值化處理threshold()函數不一樣類型的處理算法如表2所示。
其對應的閾值化描述如圖20所示:
閾值化處理普遍應用於各行各業,好比生物學中的細胞圖分割、交通領域的車牌識別等。經過閾值化處理將所圖像轉換爲黑白兩色圖,從而爲後續的圖像識別和圖像分割提供更好的支撐做用。下面詳細講解五種閾值化處理算法。
1.二進制閾值化
該函數的原型爲threshold(Gray,127,255,cv2.THRESH_BINARY)。其方法首先要選定一個特定的閾值量,好比127,再按照以下所示的規則進行閾值化處理。
當前像素點的灰度值大於thresh閾值時(如127),其像素點的灰度值設定爲最大值(如8位灰度值最大爲255);不然,像素點的灰度值設置爲0。如閾值爲127時,像素點的灰度值爲163,則閾值化設置爲255;像素點的灰度值爲82,則閾值化設置爲0。二進制閾值化處理的Python代碼以下所示:
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np #讀取圖片 src = cv2.imread('miao.png') #灰度圖像處理 GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) #二進制閾值化處理 r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_BINARY) #顯示圖像 cv2.imshow("src", src) cv2.imshow("result", b) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
輸出結果如圖21所示,左邊是苗族服飾的原圖,右邊是將原圖進行二進制閾值化處理的效果圖。像素值大於127的設置爲255,小於等於127設置爲0。
2.反二進制閾值化
該函數的原型爲threshold(Gray,127,255,cv2.THRESH_BINARY_INV)。其方法首先要選定一個特定的閾值量,好比127,再按照以下所示的規則進行閾值化處理。
當前像素點的灰度值大於thresh閾值時(如127),其像素點的灰度值設定爲0;不然,像素點的灰度值設置爲最大值。如閾值爲127時,像素點的灰度值爲211,則閾值化設置爲0;像素點的灰度值爲101,則閾值化設置爲255。反二進制閾值化處理的Python代碼以下所示:
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np #讀取圖片 src = cv2.imread('miao.png') #灰度圖像處理 grayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) #反二進制閾值化處理 r, b = cv2.threshold(grayImage, 127, 255, cv2.THRESH_BINARY_INV) #顯示圖像 cv2.imshow("src", src) cv2.imshow("result", b) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
圖像反二進制閾值化處理輸出結果如圖22所示:
3.截斷閾值化
該函數的原型爲threshold(Gray,127,255,cv2.THRESH_TRUNC)。圖像中大於該閾值的像素點被設定爲該閾值,小於或等於該閾值的保持不變,好比127。新的閾值產生規則以下:
好比閾值爲127時,像素點的灰度值爲167,則閾值化設置爲127;像素點的灰度值爲82,則閾值化設置爲82。截斷閾值化處理的Python代碼以下所示:
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np #讀取圖片 src = cv2.imread('miao.png') #灰度圖像處理 grayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) #截斷閾值化處理 r, b = cv2.threshold(grayImage, 127, 255, cv2.THRESH_TRUNC) #顯示圖像 cv2.imshow("src", src) cv2.imshow("result", b) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
輸出結果如圖23所示,圖像通過截斷閾值化處理將灰度值處理於0至127之間。
4.閾值化爲0
該函數的原型爲threshold(Gray,127,255,cv2.THRESH_TOZERO)。按照以下公式對圖像的灰度值進行處理。
當前像素點的灰度值大於thresh閾值時(如127),其像素點的灰度值保持不變;不然,像素點的灰度值設置爲0。如閾值爲127時,像素點的灰度值爲211,則閾值化設置爲211;像素點的灰度值爲101,則閾值化設置爲0。圖像閾值化爲0處理的Python代碼以下所示:
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np #讀取圖片 src = cv2.imread('miao.png') #灰度圖像處理 grayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) #閾值化爲0處理 r, b = cv2.threshold(grayImage, 127, 255, cv2.THRESH_TOZERO) #顯示圖像 cv2.imshow("src", src) cv2.imshow("result", b) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
輸出結果如圖24所示,該算法把比較亮的部分不變,比較暗的部分處理爲0。
5.反閾值化爲0
該函數的原型爲threshold(Gray,127,255, cv2.THRESH_TOZERO_INV)。按照以下公式對圖像的灰度值進行處理。
當前像素點的灰度值大於thresh閾值時(如127),其像素點的灰度值設置爲0;不然,像素點的灰度值保持不變。如閾值爲127時,像素點的灰度值爲211,則閾值化設置爲0;像素點的灰度值爲101,則閾值化設置爲101。圖像反閾值化爲0處理的Python代碼以下所示:
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np #讀取圖片 src = cv2.imread('miao.png') #灰度圖像處理 GrayImage = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY) #二進制閾值化處理 r, b = cv2.threshold(GrayImage, 127, 255, cv2.THRESH_TOZERO_INV) #顯示圖像 cv2.imshow("src", src) cv2.imshow("result", b) #等待顯示 cv2.waitKey(0) cv2.destroyAllWindows()
輸出結果如圖25所示:
下面文件是五種固定閾值化處理的對比結果。
#encoding:utf-8 #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt #讀取圖像 img=cv2.imread('miao.png') grayImage=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #閾值化處理 ret,thresh1=cv2.threshold(grayImage,127,255,cv2.THRESH_BINARY) ret,thresh2=cv2.threshold(grayImage,127,255,cv2.THRESH_BINARY_INV) ret,thresh3=cv2.threshold(grayImage,127,255,cv2.THRESH_TRUNC) ret,thresh4=cv2.threshold(grayImage,127,255,cv2.THRESH_TOZERO) ret,thresh5=cv2.threshold(grayImage,127,255,cv2.THRESH_TOZERO_INV) #顯示結果 titles = ['Gray Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV'] images = [grayImage, thresh1, thresh2, thresh3, thresh4, thresh5] for i in range(6): plt.subplot(2,3,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
圖像固定閾值化處理對比輸出結果如圖26所示:
2.自適應閾值化處理
前面講解的是固定值閾值化處理方法,而當同一幅圖像上的不一樣部分具備不一樣亮度時,上述方法就不在適用。此時須要採用自適應閾值化處理方法,根據圖像上的每個小區域,計算與其對應的閾值,從而使得同一幅圖像上的不一樣區域採用不一樣的閾值,在亮度不一樣的狀況下獲得更好的結果。
自適應閾值化處理在OpenCV中調用cv2.adaptiveThreshold()函數實現,其原型以下所示:
- dst = adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
– src表示輸入圖像
– dst表示輸出的閾值化處理後的圖像,其類型和尺寸需與src一致
– maxValue表示給像素賦的知足條件的最大值
– adaptiveMethod表示要適用的自適應閾值算法,常見取值包括ADAPTIVE_THRESH_MEAN_C(閾值取鄰域的平均值) 或 ADAPTIVE_THRESH_GAUSSIAN_C(閾值取自鄰域的加權和平均值,權重分佈爲一個高斯函數分佈)
– thresholdType表示閾值類型,取值必須爲THRESH_BINARY或THRESH_BINARY_INV
– blockSize表示計算閾值的像素鄰域大小,取值爲三、五、7等
– C表示一個常數,閾值等於平均值或者加權平均值減去這個常數
當閾值類型thresholdType爲THRESH_BINARY時,其灰度圖像轉換爲閾值化圖像的計算公式以下所示:
當閾值類型thresholdType爲THRESH_BINARY_INV時,其灰度圖像轉換爲閾值化圖像的計算公式以下所示:
其中,dst(x,y)表示閾值化處理後的灰度值,T(x,y)表示計算每一個單獨像素的閾值,其取值以下:
- 當adaptiveMethod參數採用ADAPTIVE_THRESH_MEAN_C時,閾值T(x,y)爲blockSize×blockSize鄰域內(x,y)減去參數C的平均值。
- 當adaptiveMethod參數採用ADAPTIVE_THRESH_GAUSSIAN_C時,閾值T(x,y)爲blockSize×blockSize鄰域內(x,y)減去參數C與高斯窗交叉相關的加權總和。
下面的代碼是對比固定值閾值化與自適應閾值化處理的方法。
# -*- coding: utf-8 -*- #By:Eastmount CSDN 2020-11-12 import cv2 import numpy as np import matplotlib.pyplot as plt import matplotlib #讀取圖像 img = cv2.imread('miao.png') #圖像灰度化處理 grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #固定值閾值化處理 r, thresh1 = cv2.threshold(grayImage, 127, 255, cv2.THRESH_BINARY) #自適應閾值化處理 方法一 thresh2 = cv2.adaptiveThreshold(grayImage, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 2) #自適應閾值化處理 方法二 thresh3 = cv2.adaptiveThreshold(grayImage, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) #設置字體 matplotlib.rcParams['font.sans-serif']=['SimHei'] #顯示圖像 titles = ['灰度圖像', '全局閾值', '自適應平均閾值', '自適應高斯閾值'] #顯示圖像 titles = ['Gray Image', 'Global Thresholding', 'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding'] images = [grayImage, thresh1, thresh2, thresh3] 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()
輸出結果如圖27所示,左上角爲灰度化處理圖像;右上角爲固定值全局閾值化處理圖像(cv2.threshold);左下角爲自適應鄰域平均值分割,噪聲較多;右下角爲自適應鄰域加權平均值分割,採用高斯函數分佈,其效果相對較好。
六.本章小結
本文結合做者以前研究民族服飾及圖騰識別案例講解,主要講解了圖像點運算相關知識,從灰度化處理到灰度線性變換和灰度非線性變換,經過編寫Python代碼處理像素矩陣實現相關功能;接着講述了圖像閾值化處理,調用OpenCV的threshold()實現固定閾值化處理,調用adaptiveThreshold()函數實現自適應閾值化處理。該文知識爲後續的圖像處理提供良好的基礎。
時光嘀嗒嘀嗒的流失,這是我在CSDN寫下的第八篇年終總結,比以往時候來的更早一些。《敏而多思,寧靜致遠》,僅以此篇記念這風雨兼程的一年,這感恩的一年。列車上只寫了一半,這兩天完成,思遠,思君O(∩_∩)O
2020年8月18新開的「娜璋AI安全之家」,主要圍繞Python大數據分析、網絡空間安全、人工智能、Web滲透及攻防技術進行講解,同時分享CCF、SCI、南核北核論文的算法實現。娜璋之家會更加系統,並重構做者的全部文章,從零講解Python和安全,寫了近十年文章,真心想把本身所學所感所作分享出來,還請各位多多指教,真誠邀請您的關注!謝謝。
(By:Eastmount 2020-11-13 深夜12點夜於武漢 http://blog.csdn.net/eastmount/ )
參考文獻: [1] 岡薩雷斯著,阮秋琦譯. 數字圖像處理(第3版)[M]. 北京:電子工業出版社,2013. [2] 張錚,王豔平,薛桂香等. 數字圖像處理與機器視覺——Visual C++與Matlab實現[M]. 北京:人民郵電出版社,2014. [3] 阮秋琦. 數字圖像處理學(第3版)[M]. 北京:電子工業出版社,2008. [4] 毛星雲,冷雪飛. OpenCV3編程入門[M]. 北京:電子工業出版社,2015.