天天看點

Opencv之直方圖

Opencv之直方圖

如上圖所示,直方圖統計的是一張圖檔中所含不同像素值的個數,橫坐标為像素值,縱坐标為此像素值在圖中的個數。如像素值為0的像素點在圖中有100個,則在直方圖中的第一列對應的縱坐标為100。(如果第一列對應的是0像素值的話)

在Opencv中,有專門的函數用來計算每個像素值對應多少像素點:

cv2.calcHist(images,channels,mask,histSize,ranges)

  • images: 原圖像圖像格式為 uint8 或 float32。當傳入函數時應用中括号 [] 括來例如[img]
  • channels: 同樣用中括号括來它會告函數我們統幅圖像的直方圖。如果輸入圖像是灰階圖它的值就是[0];如果是彩色圖像 的傳入的參數可以是[0]、[1]、[2] 它們分别對應着 B、G、R。
  • mask: 掩模圖像。統整幅圖像的直方圖就把它為 None。但是如果你想統圖像某一分的直方圖的你就制作一個掩模圖像并使用它。
  • histSize:BIN 的數目。也應用中括号括起來。
  • ranges: 像素值範圍常為 [0, 256]。
img = cv2.imread('cat.jpg',0) #0表示灰階圖
hist = calcHist([img], [0], None, [256], [0, 256])
hist.shape
           

可以直接用plt.hist()函數繪制直方圖:

plt.hist(img.ravel(), 256)
plt.show()
           

也可以利用得到的hist繪制直方圖:

plt.plot(hist)
plt.show()
           

如果輸入圖像是彩色的,可以繪制不同通道的直方圖:

img = cv2.imread('cat.jpg') 
color = ('b','g','r')
for i, col in enumerate(color):
	histr = cv2.calcHist([img], [i], None, [256], [0, 256])
	plt.plot(histr, color=col)
	plt.xlim([0, 256])
           

如果隻需要對一張圖檔中的某個區域繪制直方圖,則可以使用掩膜操作:

# 建立mask
mask = np.zeros(img.shape[:, 2], np.uint8)
print(mask.shape)
mask[100: 300, 100: 400] = 255
# 導入原始圖檔
img = cv2.imread('cat.jpg', 0)
# 執行“與”操作,完成掩膜
masked_img = cv2.bitwise_and(img, img, mask=mask)
# 統計直方圖
hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_full = cv2.calcHist([img], [0], mask, [256], [0, 256])
# 繪圖檢視效果
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])
plt.show()
           

有時,我們需要利用直方圖均衡化使圖檔更加明顯。

其原理其實就是将原始的像素值進行映射,得到更分散的直方圖:

如某圖檔有以下像素值。

Opencv之直方圖

可見映射後像素值之間的差距變小了。

Opencv中,有專門的函數cv2.equalizeHist()來實作均衡化。

# 原始圖像直方圖
img = cv2.imread('clahe.jpg',0) #0表示灰階圖 #clahe
plt.hist(img.ravel(),256); 
plt.show()
# 均衡化後的直方圖
equ = cv2.equalizeHist(img) 
plt.hist(equ.ravel(),256)
plt.show()
           

但有時,直方圖均衡化會分散圖中某些部分的資訊,如下圖:

Opencv之直方圖

經過均衡化之後,圖檔中雕塑的輪廓不易被看清了。

是以,我們需要使用自适應直方圖均衡化,将整張圖檔分成幾個部分來分别均衡化,然後再組合在一起。用于生成自适應均衡化圖像的函數為:

cv2.createCLAHA(clipLimit, titleGridSize)

  • clipLimit顔色對比度的門檻值。
  • titleGridSize進行像素均衡化的網格大小,即在多少網格下進行直方圖的均衡化操作。
# 執行個體化自适應直方圖均衡化函數
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
# 進行自适應直方圖均衡化
res_clahe = clahe.apply(img)
# 進行圖像的展示
res = np.hstack((img, equ, res_clahe))
cv2.imshow('res',res)
cv2.waitKey()
cv2.destroyAllWindows()
           

繼續閱讀