# Python+OpenCV圖像處理之直方圖統計的示例分析
## 摘要
本文詳細講解使用Python+OpenCV進行圖像直方圖統計的原理與實踐,涵蓋灰度/彩色直方圖計算、可視化分析、均衡化處理等核心內容,并提供完整代碼示例和效果對比。
## 一、直方圖基礎理論
### 1.1 直方圖的數學定義
直方圖是圖像像素強度分布的統計圖形表示,數學表達式為:
H(k) = n_k, k ∈ [0,L-1]
其中:
- L為灰度級數(通常256)
- n_k為圖像中灰度值為k的像素個數
### 1.2 直方圖的圖像分析意義
1. **亮度分析**:直方圖峰值左偏表示圖像偏暗,右偏表示過亮
2. **對比度評估**:分布范圍窄則對比度低
3. **特征提取**:可用于目標檢測的前期處理
4. **質量診斷**:識別過曝/欠曝問題
## 二、OpenCV直方圖計算
### 2.1 基礎API說明
```python
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
參數詳解:
- images
:輸入圖像列表(需用[]包裹)
- channels
:要統計的通道索引
- mask
:可選掩膜(None表示全圖)
- histSize
:直方圖bin數量
- ranges
:像素值范圍(通常[0,256])
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('lena.jpg', 0) # 灰度模式讀取
hist = cv2.calcHist([img], [0], None, [256], [0,256])
plt.figure(figsize=(10,4))
plt.subplot(121), plt.imshow(img, 'gray')
plt.subplot(122), plt.plot(hist)
plt.xlim([0,256])
plt.show()
img = cv2.imread('test.jpg')
colors = ('b','g','r')
plt.figure(figsize=(12,5))
for i,color in enumerate(colors):
hist = cv2.calcHist([img], [i], None, [256], [0,256])
plt.plot(hist, color=color)
plt.title('RGB Channel Histogram')
通過變換函數:
s_k = T(r_k) = (L-1) * Σ(p_r(r_j)), j=0→k
將原始直方圖分布改為均勻分布,增強對比度。
# 灰度圖均衡化
equ = cv2.equalizeHist(img)
res = np.hstack((img, equ)) # 并排對比
# 彩色圖均衡化(需分通道處理)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
hsv[:,:,2] = cv2.equalizeHist(hsv[:,:,2])
equ_color = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
通過模板直方圖在目標圖像中尋找相似區域,常用于: - 目標跟蹤 - 圖像分割 - 顏色識別
roi = cv2.imread('roi.jpg')
target = cv2.imread('target.jpg')
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
hsv_tar = cv2.cvtColor(target, cv2.COLOR_BGR2HSV)
roi_hist = cv2.calcHist([hsv_roi], [0,1], None, [180,256], [0,180,0,256])
dst = cv2.calcBackProject([hsv_tar], [0,1], roi_hist, [0,180,0,256], 1)
# 結果二值化顯示
ret, thresh = cv2.threshold(dst, 50, 255, 0)
def adjust_exposure(img, gamma=1.0):
invGamma = 1.0 / gamma
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
return cv2.LUT(img, table)
corrected = adjust_exposure(img, gamma=0.4)
def hist_compare(img1, img2):
hist1 = cv2.calcHist([img1], [0], None, [256], [0,256])
hist2 = cv2.calcHist([img2], [0], None, [256], [0,256])
return cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
similarity = hist_compare(img1, img2)
print(f"Similarity: {similarity:.2f}")
small = cv2.resize(img, (0,0), fx=0.5, fy=0.5)
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 200:400] = 255
hist = cv2.calcHist([img], [0], mask, [256], [0,256])
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 計算并繪制直方圖
hist = cv2.calcHist([gray], [0], None, [256], [0,256])
plt.clf()
plt.plot(hist)
plt.pause(0.01)
cv2.imshow('Frame', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
”`
注:本文實際約3700字(含代碼),可根據需要調整理論部分篇幅或增加更多應用案例。建議配合Jupyter Notebook實際操作示例代碼。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。