直方圖簡介:圖像的直方圖是用來表現(xiàn)圖像中亮度分布的直方圖,給出的是圖像中某個(gè)亮度或者某個(gè)范圍亮度下共有幾個(gè)像素作儿。比如一幅圖里面有2000 個(gè)像素其灰度值為12,那么就能夠統(tǒng)計(jì)12這個(gè)亮度的像素為2000個(gè),其他類推。
一、安裝matplotlib
要畫直方圖必須要安裝matplotlib庫,Matplotlib 是一個(gè) Python 的 2D繪圖庫栓霜。
安裝步驟:
運(yùn)行cmd坦袍,然后在自己的python安裝路徑的Scripts文件夾目錄下,輸入命令: pip install matplotlib
二避乏、直方圖繪制
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
def plot_demo(image):
? ? plt.hist(image.ravel(),256,[0,256])? #numpy的ravel函數(shù)功能是將多維數(shù)組降為一維數(shù)組
? ? plt.show()
#三通道圖像的直方圖
def image_hist(image):
? ? color = ('blue','green','red')? #這里畫筆顏色的值可以為大寫或小寫或只寫首字母或大小寫混合
? ? for i,color in enumerate(color):
? ? ? ? hist = cv.calcHist([image],[i],None,[256],[0,256])
? ? ? ? plt.plot(hist,color=color)
? ? ? ? plt.xlim([0,256])
? ? plt.show()
img=cv.imread("D:/temp/img/lena.jpg")
cv.imshow("img",img)
image_hist(img)
cv.waitKey (0)
cv.destroyAllWindows()
注意:
1、matplotlib.pyplot.hist函數(shù)主要是計(jì)算直方圖甘桑。
hist函數(shù)原型: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參數(shù)表示是一個(gè)數(shù)組或一個(gè)序列拍皮,是指定每個(gè)bin(箱子)分布的數(shù)據(jù)
bins參數(shù)表示指定bin(箱子)的個(gè)數(shù),也就是總共有幾條條狀圖
range參數(shù)表示箱子的下限和上限。即橫坐標(biāo)顯示的范圍扇住,范圍之外的將被舍棄春缕。
2.enumerate() 函數(shù)用于將一個(gè)可遍歷的數(shù)據(jù)對象(如列表、元組或字符串)組合為一個(gè)索引序列艘蹋,同時(shí)列出數(shù)據(jù)下標(biāo)和數(shù)據(jù)锄贼,一般用在 for 循環(huán)當(dāng)中。
3.cv2.calcHist的原型為:calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) -> hist
images參數(shù)表示輸入圖像女阀,傳入時(shí)應(yīng)該用中括號[ ]括起來
channels參數(shù)表示傳入圖像的通道宅荤,如果是灰度圖像屑迂,那就不用說了,只有一個(gè)通道冯键,值為0惹盼,如果是彩色圖像(有3個(gè)通道),那么值為0,1,2,中選擇一個(gè)惫确,對應(yīng)著BGR各個(gè)通道手报。這個(gè)值也得用[ ]傳入。
mask參數(shù)表示掩膜圖像改化。如果統(tǒng)計(jì)整幅圖掩蛤,那么為None。主要是如果要統(tǒng)計(jì)部分圖的直方圖陈肛,就得構(gòu)造相應(yīng)的掩膜來計(jì)算揍鸟。
histSize參數(shù)表示灰度級的個(gè)數(shù),需要中括號句旱,比如[256]
ranges參數(shù)表示像素值的范圍阳藻,通常[0,256]。此外谈撒,假如channels為[0,1],ranges為[0,256,0,180],則代表0通道范圍是0-256,1通道范圍0-180腥泥。
hist參數(shù)表示計(jì)算出來的直方圖。
三港华、直方圖均衡化(即調(diào)整圖像的對比度)
#全局直方圖均衡化
def eaualHist_demo(image):
? ? gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)? ? #opencv的直方圖均衡化要基于單通道灰度圖像
? ? dst = cv.equalizeHist(gray)? ? ? #自動調(diào)整圖像對比度道川,把圖像變得更清晰
? ? 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.imshow("clahe_demo", dst)
注意:
1.cv2.equalizeHist函數(shù)原型:equalizeHist(src[, dst]) -> dst午衰。函數(shù)equalizeHist的作用:直方圖均衡化立宜,提高圖像質(zhì)量。
2.直方圖均衡化:如果一副圖像的像素占有很多的灰度級而且分布均勻臊岸,那么這樣的圖像往往有高對比度和多變的灰度色調(diào)橙数。直方圖均衡化就是一種能僅靠輸入圖像直方圖信息自動達(dá)到這種效果的變換函數(shù)。它的基本思想是對圖像中像素個(gè)數(shù)多的灰度級進(jìn)行展寬帅戒,而對圖像中像素個(gè)數(shù)少的灰度進(jìn)行壓縮灯帮,從而擴(kuò)展像元取值的動態(tài)范圍,提高了對比度和灰度色調(diào)的變化逻住,使圖像更加清晰钟哥。
3.全局直方圖均衡化可能得到是一種全局意義上的均衡化,但是有的時(shí)候這種操作并不是很好瞎访,會把某些不該調(diào)整的部分給調(diào)整了腻贰。Opencv中還有一種直方圖均衡化,它是一種局部直方圖均衡化扒秸,也就是是說把整個(gè)圖像分成許多小塊(比如按10*10作為一個(gè)小塊)播演,那么對每個(gè)小塊進(jìn)行均衡化冀瓦。
4.createCLAHE函數(shù)原型:createCLAHE([, clipLimit[, tileGridSize]]) -> retval
clipLimit參數(shù)表示對比度的大小。
tileGridSize參數(shù)表示每次處理塊的大小 写烤。
四翼闽、直方圖比較
1、直方圖比較應(yīng)用
(1)圖像相似度比較
如果我們有兩張圖像洲炊,并且這兩張圖像的直方圖一樣感局,或者有極高的相似度,那么在一定程度上暂衡,我們可以認(rèn)為這兩幅圖是一樣的蓝厌,這就是直方圖比較的應(yīng)用之一。
(2)分析圖像之間關(guān)系
兩張圖像的直方圖反映了該圖像像素的分布情況古徒,可以利用圖像的直方圖拓提,來分析兩張圖像的關(guān)系。
2隧膘、直方圖比較原理
要比較兩個(gè)直方圖(H1 和 H2)代态,首先必須要選擇一個(gè)衡量直方圖相似度的對比標(biāo)準(zhǔn),我們設(shè)為d(H1,H2)疹吃。
3蹦疑、直方圖比較方法
(1)Bhattacharyya distance(巴氏距離)
在直方圖相似度計(jì)算時(shí),巴氏距離獲得的效果最好萨驶,但計(jì)算是最為復(fù)雜的歉摧。巴氏距離的計(jì)算結(jié)果,其值完全匹配為0腔呜,完全不匹配則為1叁温。
(2)相關(guān)性比較(Correlation)
相關(guān)性比較計(jì)算結(jié)果,其值完全匹配為1核畴,完全不匹配則為0膝但。
(3)Chi-Square(卡方比較)
卡方比較則是,值為0時(shí)相似度最高谤草,卡方值越小跟束,偏差越小,卡方值越大丑孩,越不符合冀宴。
import cv2 as cv
import numpy as np
def create_rgb_hist(image):
? ? h,w,c=image.shape
? ? rgbHist=np.zeros([16*16*16,1],np.float32)
? ? bsize=256/16
? ? for row in range(h):
? ? ? ? for col in range(w):
? ? ? ? ? ? b = image[row, col, 0]
? ? ? ? ? ? g = image[row, col, 1]
? ? ? ? ? ? r = image[row, col, 2]
? ? ? ? ? ? index = np.int(b/bsize)*16*16 + np.int(g/bsize)*16 + np.int(r/bsize)
? ? ? ? ? ? rgbHist[np.int(index),0] = rgbHist[np.int(index),0]+1
? ? return? rgbHist
def hist_compare(image1,image2):
? ? hist1 = create_rgb_hist(image1)
? ? hist2 = create_rgb_hist(image2)
? ? match1 = cv.compareHist(hist1,hist2,cv.HISTCMP_BHATTACHARYYA) #巴氏距離
? ? match2 = cv.compareHist(hist1, hist2, cv.HISTCMP_CORREL)? #相關(guān)性
? ? match3 = cv.compareHist(hist1, hist2, cv.HISTCMP_CHISQR)? #卡方
? ? print("巴氏距離:%s,相關(guān)性:%s温学,卡方:%s"%(match1,match2,match3))
img1=cv.imread("D:/temp/img/lena.jpg")
img2=cv.imread("D:/temp/img/lena_tmpl.jpg")
cv.imshow("img1",img1)
cv.imshow("img2",img2)
hist_compare(img1,img2)
cv.waitKey (0)
cv.destroyAllWindows()
五略贮、直方圖反向投影原理與應(yīng)用
1、基本概念
反向投影一般用來在輸入圖像(一般來說比較大)中查找與特定圖像/模板圖象(一般比較小)最匹配的點(diǎn)或者區(qū)域。也就是說刨肃,給你一個(gè)模板圖像古拴,在輸入圖像中找到和模板圖像最相近的圖像。
函數(shù)cv2.calcBackProject用來計(jì)算直方圖反向投影真友。
函數(shù)原型:calcBackProject(images, channels, hist, ranges, scale[, dst]) -> dst
images參數(shù)表示輸入圖像(是HSV圖像)黄痪。傳入時(shí)應(yīng)該用中括號[ ]括起來。
channels參數(shù)表示用于計(jì)算反向投影的通道列表盔然,通道數(shù)必須與直方圖維度相匹配桅打。
hist參數(shù)表示輸入的模板圖像直方圖。
ranges參數(shù)表示直方圖中每個(gè)維度bin的取值范圍 (即每個(gè)維度有多少個(gè)bin)愈案。
scale參數(shù)表示可選輸出反向投影的比例因子挺尾,一般取1。
2站绪、直方圖反向投影技術(shù)(通過二維直方圖反映遭铺,必須先把原圖像轉(zhuǎn)換為hsv)
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.imshow("sample", sample)
? ? cv.imshow("target", target)
? ? roiHist = cv.calcHist([roi_hsv], [0, 1], None, [32, 30], [0, 180, 0, 256])#計(jì)算樣本直方圖? [32, 30]越小,效果越好
? ? cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX) #規(guī)劃到0-255之間
? ? dst = cv.calcBackProject([target_hsv], [0,1], roiHist, [0, 180, 0, 256], 1) #計(jì)算反向投影
? ? cv.imshow("back_projection_demo", dst)