灰度直方圖
灰度直方圖是表示圖像中灰度值分布的直方圖,標繪了圖像中每個灰度值的像素數
橫坐標:圖像中各個像素點的灰度級
縱坐標:具有該灰度級的像素個數
歸一化直方圖
歸一化直方圖是表示圖像中灰度值分布的概率之和等於1
橫坐標:圖像中各個像素點的灰度級
縱坐標:出現這個灰度級的概率
需要注意的,直方圖術語:
dims:需要統計的特征的數目。當dims=1時,表示我們僅統計灰度值
bins:每個特征空間子區段的數目
range:每個特征空間的取值范圍
使用python中matplotlib庫來繪制直方圖
import matplotlib.pyplot as plt
函數hist(數據源,像素級),根據數據源和像素級繪制直方圖
其中,數據源必須是一維數組圖像;像素級一般是256,指[0,255]
通過ravel()函數,將多維的數組,轉化為一維的形式
# 將繪制的圖顯示在窗口 %matplotlib qt5 import cv2 import matplotlib.pyplot as plt img = cv2.imread(r"image\boat.jpg",cv2.IMREAD_COLOR) # 彩色圖像轉化為灰度圖 img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # ravel()函數,將二維的圖像,轉化為一維的數組 img_2 = img.ravel() cv2.imshow("original",img) # 1.設置rc參數顯示中文標題,設置字體為SimHei顯示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 2.繪制灰度直方圖 plt.hist(img_2,256) plt.xlabel("灰度級") plt.ylabel("像素個數") plt.title("灰度直方圖") # 3.顯示灰度直方圖 plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
使用opencv來繪制統計直方圖
hist = cv2.calcHist(images,channels,mask,histSize,ranges[,accumulate])
返回的hist直方圖,相當於縱坐標的值,也就是具有灰度級像素個數的二維數組
1>channels:指定通道
通道的編號需要用中括號括起來,當輸入圖像是灰度圖時,對應的通道是[0];當輸入圖像是彩色圖像時,通道[0],[1],[2]分別對應B,G,R
2>mask:掩碼圖像
統計整幅圖像的直方圖,設為None;統計圖像某一部分的直方圖時,需要掩碼圖像
3>histSize:BINS的數量
每個特征空間子區段的數目,一般是256,需要用中括號括起來
4>range:每個特征空間的取值范圍
一般是[0,255],需要用中括號括起來
5>accumulate:累計標識(可選參數)
默認值為False,如果被設置為True,則直方圖在開始分配時不會被清零。也就是說計算一組圖像的直方圖
import cv2 import numpy as np # 輸入圖像是灰度圖 img = cv2.imread(r"image\boat.bmp",cv2.IMREAD_GRAYSCALE) # 繪制統計直方圖 hist = cv2.calcHist([img],[0],None,[256],[0,255]) print("統計直方圖的類型:",type(hist)) print("統計直方圖的大小:",hist.size) print("統計直方圖的形狀:",hist.shape)
import matplotlib.pyplot as plt
(如果是彩色圖像,需要分別繪制BGR三個通道的直方圖)
# 將繪制的圖顯示在窗口 %matplotlib qt5 import cv2 import matplotlib.pyplot as plt # 輸入圖像時彩色圖像 img = cv2.imread(r"image\girl.bmp",cv2.IMREAD_COLOR) cv2.imshow("original",img) # 繪制統計直方圖 histb = cv2.calcHist([img],[0],None,[256],[0,255]) histg = cv2.calcHist([img],[1],None,[256],[0,255]) histr = cv2.calcHist([img],[2],None,[256],[0,255]) # 1.設置rc參數顯示中文標題,設置字體為SimHei顯示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 2.繪制灰度直方圖 plt.plot(histb,color="b") plt.plot(histg,color="g") plt.plot(histr,color="r") plt.xlabel("灰度級") plt.ylabel("像素個數") plt.title("統計直方圖") # 3.顯示灰度直方圖 plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
使用掩膜mask的直方圖
圖像掩模一般用來對處理的圖像(全部或者局部)進行遮擋,來控制圖像處理的區域或處理過程
生成掩膜mask圖像,一般需要兩步:
1> mask = np.zeros(image.shape,np.uint8)
第一步,建立與原圖一樣大小的mask圖像,並將所有像素初始化為0,也就是一張全黑色的圖
2> mask[200:400,200:400] = 255
第二步,將mask圖中指定區域的所有像素值設置為255,也就是將整個指定區域變成了白色
還是使用opencv來繪制統計直方圖
hist = cv2.calcHist(images,channels,mask,histSize,ranges[,accumulate])
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r"image\boat.bmp",cv2.IMREAD_GRAYSCALE) cv2.imshow("original",img) # 生成掩膜mask圖像 mask = np.zeros(img.shape,np.uint8) mask[200:400,200:400] = 255 cv2.imshow("mask",mask) # 繪制統計直方圖 hist = cv2.calcHist([img],[0],mask,[256],[0,255]) # 1.設置rc參數顯示中文標題,設置字體為SimHei顯示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 2.繪制灰度直方圖 plt.plot(hist) plt.xlabel("灰度級") plt.ylabel("像素個數") plt.title("統計直方圖") # 3.顯示灰度直方圖 plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
直方圖均衡化
直方圖均衡化是一種簡單有效的圖像增強技術,將圖像的直方圖分布變成近似均勻分布,從而增強圖像的對比度,使色彩細節更豐富,多用於車牌識別、人臉識別場景
直方圖均衡化的過程:
1> 計算累計直方圖
2> 將累計直方圖進行區間轉換
使用opencv繪制直方圖均衡化
dst = cv2.equalizeHist(src)
其中,src是源圖像,dst是目標圖像(處理結果)
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r"image\equ.bmp",cv2.IMREAD_GRAYSCALE) # 設置rc參數顯示中文標題,設置字體為SimHei顯示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 繪制灰度直方圖 # ravel()函數,將二維的圖像,轉化為一維的數組 plt.hist(img.ravel(),256) plt.xlabel("灰度級") plt.ylabel("像素個數") plt.title("灰度直方圖") # 繪制均衡直方圖 # plt.figure()函數,創建自定義圖像 plt.figure() equ = cv2.equalizeHist(img) plt.hist(equ.ravel(),256) plt.xlabel("灰度級") plt.ylabel("像素個數") plt.title("均衡直方圖") # 3.顯示灰度直方圖 plt.show() cv2.imshow("original",img) cv2.imshow("result",equ) cv2.waitKey(0) cv2.destroyAllWindows()
需要注意:也可以通過plt.subplot()函數,繪制多個子窗口
import matplotlib.pyplot as plt
plt.subplot(nrows,ncols,plot_number)
其中,nrows是行數,ncols是列數,plot_number是窗口序號
# 將繪制的圖顯示在窗口 %matplotlib qt5 import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r"image\equ.bmp",cv2.IMREAD_GRAYSCALE) # 設置rc參數顯示中文標題,設置字體為SimHei顯示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 通過plt.subplot()繪制一個一行兩列的子窗口 # 1.繪制灰度直方圖 plt.subplot(1,2,1) plt.hist(img.ravel(),256) plt.xlabel("灰度級") plt.ylabel("像素個數") plt.title("灰度直方圖") # 2.繪制均衡直方圖 plt.subplot(1,2,2) equ = cv2.equalizeHist(img) plt.hist(equ.ravel(),256) plt.xlabel("灰度級") plt.ylabel("像素個數") plt.title("均衡直方圖") # 3.顯示灰度直方圖 plt.show()
需要注意:也可以通過plt.imshow()函數,顯示opencv讀入的圖像
import matplotlib.pyplot as plt
plt.imshow(x,cmap)
其中,x是要繪制的圖像,cmap是顏色圖譜
# 將繪制的圖顯示在窗口 %matplotlib qt5 import cv2 import numpy as np import matplotlib.pyplot as plt # 讀取一個彩色圖像 img = cv2.imread(r"image\girl.bmp",cv2.IMREAD_COLOR) # 彩色圖像轉換灰度圖像 img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 設置rc參數顯示中文標題,設置字體為SimHei顯示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 通過plt.subplot()繪制一個一行兩列的子窗口 # 1.顯示彩色圖像 plt.subplot(1,2,1) # 拆分通道 b,g,r = cv2.split(img) # 合並通道 rgb_img = cv2.merge([r,g,b]) plt.imshow(rgb_img) plt.title("彩色圖像") # 關閉坐標軸 plt.axis("off") # 2.顯示灰度圖像 plt.subplot(1,2,2) plt.imshow(img_gray,cmap=plt.cm.gray) plt.title("灰度圖像") # 關閉坐標軸 plt.axis("off") # 3.顯示灰度直方圖 plt.show()