天天看點

【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

文章目錄

  • 十、圖象直方圖
    • 1、圖像直方圖的基本概念
    • 2、使用OpenCV統計直方圖
    • 3、使用OpenCV繪制直方圖
    • 4、使用掩膜的直方圖
    • 5、直方圖均衡化

十、圖象直方圖

1、圖像直方圖的基本概念

在統計學中,直方圖是一種對資料分布情況的圖形展示,是一種二維統計圖表。

圖像直方圖是用來表示數字圖像中亮度分布的直方圖,标繪了圖像中每個亮度值的像素數。可以借助觀察該直方圖了解需要如何調整亮度分布的直方圖。在這種直方圖中,橫坐标的左側為純黑、較暗的區域,而右側為較亮、純白的區域。是以,一張較暗圖像的圖像直方圖中的資料多集中于左側和中間部分,而整體明亮、隻有少量陰影的圖像則相反。

  • 橫坐标: 圖像中各個像素點的灰階級。
  • 縱坐标: 具有該灰階級的像素個數。
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
  • 畫出上圖的直方圖:
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
  • 或者以柱狀圖的形式:
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
  • 歸一化直方圖
    • 橫坐标:圖像中各個像素點的灰階級。
    • 縱坐标:出現灰階級的機率。
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
  • 直方圖術語:
    • dims

      :需要統計的特征數目。例如,

      dims = 1

      ,表示我們僅統計灰階值。
    • bins

      :每個特征空間子區段的數目。
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

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()
           
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

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()
           
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

4、使用掩膜的直方圖

  • 掩膜
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
  • 如何生成掩膜:
    • 先生成一個全黑的和原始圖像大小一樣的圖像:

      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()
           

使用掩膜的圖像:

【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

使用掩膜的圖像直方圖:

【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

5、直方圖均衡化

直方圖均衡化是通過拉伸像素強度的分布範圍,使得在0~255灰階上的分布更加均衡,提高圖像的對比度,達到改善圖像主觀視覺效果的目的。

對比度較低的圖像适合使用直方圖均衡化方法來增加圖像細節。

【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

原理:

  • 計算累計直方圖
  • 将累計直方圖進行區間轉換
  • 在累計直方圖中,機率相近的原始值,會被處理為相同的值
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

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()
           
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖
【OpenCV圖像處理10】圖像直方圖十、圖象直方圖

繼續閱讀