圖像直方圖
那么,圖像直方圖到底是什么?
圖片
圖像的構(gòu)成是由像素點(diǎn)構(gòu)成的,每個像素點(diǎn)的值代表著該點(diǎn)的顏色(灰度圖或者彩色圖)。所謂直方圖就是對圖像的中的這些像素點(diǎn)的值進(jìn)行統(tǒng)計,得到一個統(tǒng)一的整體的灰度概念。直方圖表示圖像中顏色的分布??梢詫⑵淇梢暬癁閳D表(或曲線圖),以直觀地了解強(qiáng)度(像素值)分布。直方圖的好處就在于可以清晰了解圖像的整體灰度分布,這對于計算機(jī)視覺處理圖片有關(guān)重要。
一般情況下直方圖都是灰度圖像,直方圖x軸是灰度值(一般0~255),y軸就是圖像中每一個灰度級對應(yīng)的像素點(diǎn)的個數(shù)。
灰度空間圖片直方圖
如何獲取圖片直方圖
圖片直方圖的獲取,opencv已經(jīng)幫我們集成了函數(shù),當(dāng)然numpy也同樣可以 獲取
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
#numpy方法讀取-np.histogram()
#hist_np,bins = np.histogram(img.ravel(),256,[0,256])
#numpy的另一種方法讀取-np.bincount()
#hist_np1 = np.bincount(img.ravel(),minlength=256)
cv2.imshow("gray", img)
plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.show()
代碼截圖
cv2.calcHist(),該函數(shù)傳遞5個參數(shù):
- image輸入圖像,此參數(shù)是一個list 對象
- channels::傳入圖像的通道,如果是灰度圖像,只有一個通道,值為0,如果是彩色圖像(B G R),那么值為0,1,2,中選擇一個,對應(yīng)著BGR各個通道。同樣為list 對象。
- mask:掩膜圖像。如果統(tǒng)計整幅圖,那么為none。主要是如果要統(tǒng)計部分圖的直方圖,就得構(gòu)造相應(yīng)的掩膜圖像來計算。
- histSize:灰度級的個數(shù),比如[256],或者三個通道的[32,32,32]
- ranges:像素值的范圍,通常[0,256],通常,這是[0, 256]針對每個通道的,但是如果您使用的顏色空間不是RGB(例如HSV),則范圍可能會有所不同。
以上展示了圖片在灰度值中的顏色直方圖,當(dāng)然,我們的圖片是R G B的三色圖片,我們也可以分別展示圖片在R G B 空間內(nèi)的圖片直方圖。
彩色空間圖片直方圖
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
cv2.imshow("image", image)
chans = cv2.split(image)
colors = ("b", "g", "r")
plt.figure()
plt.title("'Flattened' Color Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
features = []
for (chan, color) in zip(chans, colors):
hist = cv2.calcHist([chan], [0], None, [256], [0, 256])
features.extend(hist)
plt.plot(hist, color = color)
plt.xlim([0, 256])
plt.show()
代碼截圖
chans = cv2.split(image)函數(shù)把圖片分別分割成 R G B 三色空間
分別把三色空間的 R G B 空間傳入cv2.calcHist([chan], [0], None, [256], [0, 256])函數(shù)來生成不同空間內(nèi)的顏色圖片直方圖,最后把圖片顯示出來
圖片mask參數(shù)
cv2.calcHist函數(shù)可以接受mask 來進(jìn)行圖片直方圖的顯示,默認(rèn)計算圖片的所有區(qū)域,但是有時候我們不需要圖片的所有區(qū)域,我們可以使用mask來扣自己需要的圖片區(qū)域,進(jìn)而可以進(jìn)行自己想要圖片區(qū)域的直方圖
mask 圖片直方圖
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
mask = np.zeros(img.shape[:2],np.uint8)
mask[100:500,100:500] = 255
mask_img = cv2.bitwise_and(img,img,mask=mask)
hist = cv2.calcHist([img], [0], mask, [256], [0, 256])
cv2.imshow("mask", mask_img)
plt.figure()
plt.title("Grayscale Histogram")
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
plt.plot(hist)
plt.show()
代碼截圖
首先我們獲取圖片的尺寸img.shape[:2],有了圖片的尺寸
我們可以標(biāo)注自己需要的圖片區(qū)域mask[100:500,100:500] = 255
使用cv2.bitwise_and 函數(shù)把原來圖片中的需要的局部區(qū)域提取出來,我們可以show一下,看看是否是自己需要的區(qū)域
有了mask的區(qū)域,使用cv2.calcHist([img], [0], mask, [256], [0, 256])函數(shù),傳遞mask 參數(shù),進(jìn)而可以實(shí)現(xiàn)mask圖片的直方圖顯示。
圖片直方圖均衡化
這種方法通常用來增加許多圖像的全局對比度,尤其是當(dāng)圖像的有用數(shù)據(jù)的對比度相當(dāng)接近的時候。通過這種方法,亮度可以更好地在直方圖上分布。這樣就可以用于增強(qiáng)局部的對比度而不影響整體的對比度,直方圖均衡化通過有效地擴(kuò)展常用的亮度來實(shí)現(xiàn)這種功能。
這種方法對于背景和前景都太亮或者太暗的圖像非常有用,這種方法尤其是可以帶來X光圖像中更好的骨骼結(jié)構(gòu)顯示以及曝光過度或者曝光不足照片中更好的細(xì)節(jié)。這種方法的一個主要優(yōu)勢是它是一個相當(dāng)直觀的技術(shù)并且是可逆操作,如果已知均衡化函數(shù),那么就可以恢復(fù)原始的直方圖,并且計算量也不大。這種方法的一個缺點(diǎn)是它對處理的數(shù)據(jù)不加選擇,它可能會增加背景噪聲的對比度并且降低有用信號的對比度。
圖片直方圖均衡化
有兩個問題比較難懂,一是為什么要選用累積分布函數(shù),二是為什么使用累積分布函數(shù)處理后像素值會均勻分布。
直方圖均衡化包括三個步驟:
- 統(tǒng)計直方圖中每個灰度級出現(xiàn)的次數(shù);
- 計算累計歸一化直方圖;
- 重新計算像素點(diǎn)的像素值;
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
res = cv2.equalizeHist(img)
cv2.imshow('img',img)
cv2.imshow('res',res)
cv2.waitKey(0)
代碼截圖
opencv 使用此函數(shù)res = cv2.equalizeHist(img),對圖片進(jìn)行均衡化進(jìn)行處理,此函數(shù)是opencv全局化操作,這個操作在我們需要局部調(diào)整時不太適用,同理mask參數(shù),opencv存在一種局部化處理的函數(shù)cv2.createCLAHE(),此函數(shù)接受一個局部尺寸參數(shù)數(shù)據(jù)
局部化處理
from matplotlib import pyplot as plt
import numpy as np
import cv2
image = cv2.imread("1.jpg")
img = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#res = cv2.equalizeHist(img)
cla = cv2.createCLAHE(clipLimit=2,tileGridSize=(10,10))
res = cla.Apply(img)
cv2.imshow('img',img)
cv2.imshow('res',res)
cv2.waitKey(0)
代碼截圖
總結(jié)
圖片直方圖在相識圖片搜索引擎中起到了至關(guān)重要的作用,如何使用圖片直方圖來進(jìn)行相識圖片的搜索,我們下期分享,幫你打造一款屬于自己的相識圖片搜索引擎。






