文章目錄
- 十、圖象直方圖
-
- 1、圖像直方圖的基本概念
- 2、使用OpenCV統計直方圖
- 3、使用OpenCV繪制直方圖
- 4、使用掩膜的直方圖
- 5、直方圖均衡化
十、圖象直方圖
1、圖像直方圖的基本概念
在統計學中,直方圖是一種對資料分布情況的圖形展示,是一種二維統計圖表。
圖像直方圖是用來表示數字圖像中亮度分布的直方圖,标繪了圖像中每個亮度值的像素數。可以借助觀察該直方圖了解需要如何調整亮度分布的直方圖。在這種直方圖中,橫坐标的左側為純黑、較暗的區域,而右側為較亮、純白的區域。是以,一張較暗圖像的圖像直方圖中的資料多集中于左側和中間部分,而整體明亮、隻有少量陰影的圖像則相反。
- 橫坐标: 圖像中各個像素點的灰階級。
- 縱坐标: 具有該灰階級的像素個數。
- 畫出上圖的直方圖:
- 或者以柱狀圖的形式:
- 歸一化直方圖
- 橫坐标:圖像中各個像素點的灰階級。
- 縱坐标:出現灰階級的機率。
- 直方圖術語:
-
:需要統計的特征數目。例如,dims
,表示我們僅統計灰階值。dims = 1
-
:每個特征空間子區段的數目。bins
-
range
:統計灰階值的範圍,一般為 [0, 255]
2、使用OpenCV統計直方圖
calcHist()
用法:
參數說明:
- images:原始圖像
- channels:指定通道
- 需要用中括号括起來,輸入圖像是灰階圖像值是 [0],彩色圖像可以是 [0],[1],[2],分别對應 B,G,R
- mask:掩碼圖像
- 統計整幅圖像的直方圖,設為 None
- 統計圖像某一部分的直方圖時,需要掩碼圖像
- histSize: BINS的數量
- 需要用中括号括起來,例如 [256]
- ranges:像素值範圍,例如 [0, 255]
- accumulate:累計辨別
- 預設值為 False
- 如果被設定為 True,則直方圖在開始配置設定時不會被清零。
- 該參數允許從多個對象中計算單個直方圖,或者用于實時更新直方圖。
- 多個直方圖的累積結果,用于一組圖像計算直方圖。
代碼實作:
import cv2
img = cv2.imread('../resource/lena.bmp')
hist = cv2.calcHist([img], [0], None, [256], [0, 255])
print(hist.size)
print(hist.shape)
print(hist)
256
(256, 1)
[[0.000e+00]
[1.000e+00]
...
3、使用OpenCV繪制直方圖
可以利用 matplotlib 把 OpenCV 統計得到的直方圖繪制出來。
1、不使用OpenCV
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('../resource/lena.bmp')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
plt.hist(gray.ravel(), bins=256, range=[0, 255])
plt.show()
2、使用OpenCV
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('../resource/lena.bmp')
hisb = cv2.calcHist([img], [0], None, [256], [0, 255])
hisg = cv2.calcHist([img], [1], None, [256], [0, 255])
hisr = cv2.calcHist([img], [2], None, [256], [0, 255])
plt.plot(hisb, color='b', label='blue')
plt.plot(hisg, color='g', label='green')
plt.plot(hisr, color='r', label='red')
plt.legend()
plt.show()
4、使用掩膜的直方圖
- 掩膜
- 如何生成掩膜:
- 先生成一個全黑的和原始圖像大小一樣的圖像:
mask = np.zeros(gray.shape, np.uint8)
- 将想要的區域通過索引方式設定為255:
mask[200:400, 200:400] = 255
- 先生成一個全黑的和原始圖像大小一樣的圖像:
代碼實作:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('../resource/lena.bmp')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 掩膜
mask = np.zeros(gray.shape, np.uint8)
mask[200:400, 200:400] = 255
cv2.imshow('img', np.hstack((gray, mask,)))
# 與運算
cv2.imshow('mask', cv2.bitwise_and(gray, gray, mask=mask))
hist_mask = cv2.calcHist([gray], [0], mask, [256], [0, 255])
hist_gray = cv2.calcHist([gray], [0], None, [256], [0, 255])
plt.plot(hist_mask, label='mask')
plt.plot(hist_gray, label='gray')
plt.legend()
plt.show()
cv2.waitKey(0)
cv2.destroyAllWindows()
使用掩膜的圖像:
使用掩膜的圖像直方圖:
5、直方圖均衡化
直方圖均衡化是通過拉伸像素強度的分布範圍,使得在0~255灰階上的分布更加均衡,提高圖像的對比度,達到改善圖像主觀視覺效果的目的。
對比度較低的圖像适合使用直方圖均衡化方法來增加圖像細節。
原理:
- 計算累計直方圖
- 将累計直方圖進行區間轉換
- 在累計直方圖中,機率相近的原始值,會被處理為相同的值
equalizeHist()
用法:
參數說明:
- src:原始圖像
- dst:目标圖像,即處理結果
代碼實作:
import cv2
import numpy as np
import matplotlib.pyplot as plt
lena = cv2.imread('../resource/lena.bmp')
gray = cv2.cvtColor(lena, cv2.COLOR_BGR2GRAY)
# lena變黑
gray_dark = gray - 40
# lena變亮
gray_bright = gray + 40
# 檢視各自直方圖
hist_gray = cv2.calcHist([gray], [0], None, [256], [0, 255])
hist_gray_dark = cv2.calcHist([gray_dark], [0], None, [256], [0, 255])
hist_gray_bright = cv2.calcHist([gray_bright], [0], None, [256], [0, 255])
# 畫出直方圖
plt.plot(hist_gray, label='gray')
plt.plot(hist_gray_dark, label='dark')
plt.plot(hist_gray_bright, label='bright')
plt.legend()
plt.show()
# 進行均衡化處理
dark_equ = cv2.equalizeHist(gray_dark)
bright_equ = cv2.equalizeHist(gray_bright)
cv2.imshow('lena', np.hstack((gray, gray_dark, gray_bright)))
cv2.imshow('gray_dark', np.hstack((gray_dark, dark_equ)))
cv2.imshow('gray_bright', np.hstack((gray_bright, bright_equ)))
cv2.waitKey(0)
cv2.destroyAllWindows()