直方圖簡介:圖像的直方圖是用來表現圖像中亮度分布的直方圖,給出的是圖像中某個亮度或者某個范圍亮度下共有幾個像素.還不明白?就是統計一幅圖某個亮度像素數量.比如對於灰度值12,一幅圖里面有2000 個像素其灰度值為12,那么就能夠統計12這個亮度的像素為2000個,其他類推。參考:https://blog.csdn.net/xierhacker/article/details/52605308
一、安裝matplotlib
要畫直方圖必須要安裝matplotlib庫,Matplotlib 是一個 Python 的 2D繪圖庫。
安裝步驟:
運行cmd,然后在自己的python安裝路徑的Scripts文件夾目錄下,輸入命令: pip install matplotlib
二、畫直方圖
代碼如下:
#畫直方圖 import cv2 as cv from matplotlib import pyplot as plt def plot_demo(image): plt.hist(image.ravel(), 256, [0, 256]) #numpy的ravel函數功能是將多維數組降為一維數組 plt.show() def image_hist(image): #畫三通道圖像的直方圖 color = ('b', 'g', 'r') #這里畫筆顏色的值可以為大寫或小寫或只寫首字母或大小寫混合 for i , color in enumerate(color): hist = cv.calcHist([image], [i], None, [256], [0, 256]) #計算直方圖 plt.plot(hist, color) plt.xlim([0, 256]) plt.show() src = cv.imread('E:/imageload/WindowsLogo.jpg') cv.namedWindow('input_image', cv.WINDOW_NORMAL) cv.imshow('input_image', src) plot_demo(src) image_hist(src) cv.waitKey(0) cv.destroyAllWindows()
運行結果:
注意:
1.numpy的ravel函數功能是將多維數組降為一維數組。參考博客:https://blog.csdn.net/lanchunhui/article/details/50354978
2.matplotlib.pyplot.hist函數主要是計算直方圖。
hist函數原型:hist(x, bins=None, range=None, density=None, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False, normed=None, hold=None, data=None, **kwargs)
x參數表示是一個數組或一個序列,是指定每個bin(箱子)分布的數據
bins參數表示指定bin(箱子)的個數,也就是總共有幾條條狀圖
range參數表示箱子的下限和上限。即橫坐標顯示的范圍,范圍之外的將被舍棄。
參考博客:https://blog.csdn.net/u013571243/article/details/48998619
3.enumerate() 函數用於將一個可遍歷的數據對象(如列表、元組或字符串)組合為一個索引序列,同時列出數據下標和數據,一般用在 for 循環當中。
4.cv2.calcHist的原型為:calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) -> hist
images參數表示輸入圖像,傳入時應該用中括號[ ]括起來
channels參數表示傳入圖像的通道,如果是灰度圖像,那就不用說了,只有一個通道,值為0,如果是彩色圖像(有3個通道),那么值為0,1,2,中選擇一個,對應着BGR各個通道。這個值也得用[ ]傳入。
mask參數表示掩膜圖像。如果統計整幅圖,那么為None。主要是如果要統計部分圖的直方圖,就得構造相應的掩膜來計算。
histSize參數表示灰度級的個數,需要中括號,比如[256]
ranges參數表示像素值的范圍,通常[0,256]。此外,假如channels為[0,1],ranges為[0,256,0,180],則代表0通道范圍是0-256,1通道范圍0-180。
hist參數表示計算出來的直方圖。
參考:https://blog.csdn.net/YZXnuaa/article/details/79231817
5.關於pyplot模塊里plot()函數、xlim()函數等的用法參考:
https://blog.csdn.net/cymy001/article/details/78344316
https://blog.csdn.net/chinwuforwork/article/details/51786967
三、直方圖的應用
代碼如下:
#直方圖的應用 直方圖均衡化(即調整圖像的對比度) 直方圖即統計各像素點的頻次 import cv2 as cv #全局直方圖均衡化 def eaualHist_demo(image): gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) #opencv的直方圖均衡化要基於單通道灰度圖像 cv.namedWindow('input_image', cv.WINDOW_NORMAL) cv.imshow('input_image', gray) dst = cv.equalizeHist(gray) #自動調整圖像對比度,把圖像變得更清晰 cv.namedWindow("eaualHist_demo", cv.WINDOW_NORMAL) cv.imshow("eaualHist_demo", dst) #局部直方圖均衡化 def clahe_demo(image): gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) clahe = cv.createCLAHE(5, (8,8)) dst = clahe.apply(gray) cv.namedWindow("clahe_demo", cv.WINDOW_NORMAL) cv.imshow("clahe_demo", dst) src = cv.imread('E:/imageload/rice.png') eaualHist_demo(src) clahe_demo(src) cv.waitKey(0) cv.destroyAllWindows()
運行結果:
注意:
1.cv2.equalizeHist函數原型:equalizeHist(src[, dst]) -> dst。函數equalizeHist的作用:直方圖均衡化,提高圖像質量。
2.直方圖均衡化:如果一副圖像的像素占有很多的灰度級而且分布均勻,那么這樣的圖像往往有高對比度和多變的灰度色調。直方圖均衡化就是一種能僅靠輸入圖像直方圖信息自動達到這種效果的變換函數。它的基本思想是對圖像中像素個數多的灰度級進行展寬,而對圖像中像素個數少的灰度進行壓縮,從而擴展像元取值的動態范圍,提高了對比度和灰度色調的變化,使圖像更加清晰。
3.全局直方圖均衡化可能得到是一種全局意義上的均衡化,但是有的時候這種操作並不是很好,會把某些不該調整的部分給調整了。Opencv中還有一種直方圖均衡化,它是一種局部直方圖均衡化,也就是是說把整個圖像分成許多小塊(比如按10*10作為一個小塊),那么對每個小塊進行均衡化。
4.createCLAHE函數原型:createCLAHE([, clipLimit[, tileGridSize]]) -> retval
clipLimit參數表示對比度的大小。
tileGridSize參數表示每次處理塊的大小 。
5.
clahe = cv.createCLAHE(5, (8,8))
dst = clahe.apply(gray) #猜測:把clahe這種局部直方圖均衡化應用到灰度圖gray
四、直方圖反向投影
代碼如下:
#直方圖反向投影技術(通過二維直方圖反映,必須先把原圖像轉換為hsv) import cv2 as cv #計算H-S直方圖 def back_projection_demo(): sample = cv.imread("E:/imageload/sample.jpg") target = cv.imread("E:/imageload/target.jpg") roi_hsv = cv.cvtColor(sample, cv.COLOR_BGR2HSV) target_hsv = cv.cvtColor(target, cv.COLOR_BGR2HSV) cv.namedWindow("sample", cv.WINDOW_NORMAL) cv.imshow("sample", sample) cv.namedWindow("target", cv.WINDOW_NORMAL) cv.imshow("target", target) roiHist = cv.calcHist([roi_hsv], [0, 1], None, [32, 30], [0, 180, 0, 256])#計算樣本直方圖 [32, 30]越小,效果越好 cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX) #規划到0-255之間 dst = cv.calcBackProject([target_hsv], [0,1], roiHist, [0, 180, 0, 256], 1) #計算反向投影 cv.namedWindow("back_projection_demo", cv.WINDOW_NORMAL) cv.imshow("back_projection_demo", dst) back_projection_demo() cv.waitKey(0) cv.destroyAllWindows()
運行結果:
注意:
1. 歸一化就是要把需要處理的數據經過處理后(通過某種算法)限制在你需要的一定范圍內。
歸一化函數cv2.normalize原型:normalize(src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]) -> dst
src參數表示輸入數組。
dst參數表示輸出與src相同大小的數組,支持原地運算。
alpha參數表示range normalization模式的最小值。
beta參數表示range normalization模式的最大值,不用於norm normalization(范數歸一化)模式。
norm_type參數表示歸一化的類型。
norm_type參數可以有以下的取值:
NORM_MINMAX:數組的數值被平移或縮放到一個指定的范圍,線性歸一化,一般較常用。
NORM_INF:歸一化數組的C-范數(絕對值的最大值)。
NORM_L1 :歸一化數組的L1-范數(絕對值的和)。
NORM_L2 :歸一化數組的(歐幾里德)L2-范數。
參考博客:https://blog.csdn.net/solomon1558/article/details/44689611
2.反向投影用於在輸入圖像(通常較大)中查找特定圖像(通常較小或者僅1個像素,以下將其稱為模板圖像)最匹配的點或者區域,也就是定位模板圖像出現在輸入圖像的位置。
函數cv2.calcBackProject用來計算直方圖反向投影。
函數原型:calcBackProject(images, channels, hist, ranges, scale[, dst]) -> dst
images參數表示輸入圖像(是HSV圖像)。傳入時應該用中括號[ ]括起來。
channels參數表示用於計算反向投影的通道列表,通道數必須與直方圖維度相匹配。
hist參數表示輸入的模板圖像直方圖。
ranges參數表示直方圖中每個維度bin的取值范圍 (即每個維度有多少個bin)。
scale參數表示可選輸出反向投影的比例因子,一般取1。
參考博客:https://blog.csdn.net/keith_bb/article/details/70154219