python中opencv 直方圖處理

直方圖處理

直方圖從圖像內部灰度級的角度對圖像進行表述從直方圖的角度對圖像進行處理,可以達到增強圖像顯示效果的目的。

直方圖的含義

直方圖是圖像內灰度值的統計特性與圖像灰度值之間的函數,直方圖統計圖像內各個灰度級出現的次數。從直方圖的圖形上觀察,橫坐標是圖像中各像素點的灰度級,縱坐標是具有該灰度級(像素值)的像素個數。在繪制直方圖時,將灰度級作為x軸處理,該灰度級出現的次數作為y軸處理

把左側的直線圖和右側直方圖都稱為直方圖

在實際處理中,圖像直方圖的x軸區間一般是[0, 255],對應的是8位位圖的256個灰度級;y軸對應的是具有相應灰度級的像素點的個數。

歸一化直方圖: 在歸一化直方圖中,x軸仍然表示灰度級;y軸不再表示灰度級出現的次數,而是灰度級出現的頻率。

灰度級出現的頻率=灰度級出現的次數/總像素數在歸一化直方圖中,各個灰度級出現的頻率之和為1。歸一化直方圖與直方圖在外觀上是一致的,隻是y軸的標簽不同而已。

在OpenCV的官網上,特別提出瞭要註意的三個概念:DIMS、BINS、RANGE

  • DIMS:表示在繪制直方圖時,收集的參數的數量。一般情況下,直方圖中收集的數據隻有一種,就是灰度級。因此,該值為1。
  • RANGE:表示要統計的灰度級范圍,一般為[0, 255]。0對應的是黑色,255對應的是白色。
  • BINS:參數子集的數目。在處理數據的過程中,有時需要將眾多的數據劃分為若幹個組,再進行分析。
    例如: 希望將兩個像素值作為一組討論

繪制直方圖

Python的模塊matplotlib.pyplot中的hist()函數能夠方便地繪制直方圖,通常采用該函數直接繪制直方圖。除此以外,OpenCV中的cv2.calcHist()函數能夠計算統計直方圖,還可以在此基礎上繪制圖像的直方圖。

使用Numpy繪制直方圖

模塊matplotlib.pyplot提供瞭一個類似於MATLAB繪圖方式的框架,可以使用其中的matplotlib.pyplot.hist()函數來繪制直方圖。此函數的作用是根據數據源和灰度級分組繪制直方圖。

其基本語法格式為:

matplotlib.pyplot.hist(X, BINS)
  • X:數據源,必須是一維的。圖像通常是二維的,需要使用ravel()函數將圖像處理為一維數據源以後,再作為參數使用。
  • BINS:BINS的具體值,表示灰度級的分組情況。

函數ravel()的作用是將二維數組降維成一維數組。

例如:數組a

使用函數ravel()對a進行處理:

b = a.ravel()

使用hist()函數繪制一幅圖像的直方圖

import cv2
import matplotlib.pyplot as plt
o=cv2.imread("./img/hand1.png")
cv2.imshow("original", o)
plt.hist(o.ravel(),256)
plt.show()
cv2.waitKey()
cv2.destroyAllWindows()

使用函數hist()將一幅圖像的灰度級劃分為16組後,繪制該圖像的直方圖。

將灰度級劃分為16組,即將灰度級劃分為16個子集,對應的BINS值為16。

import cv2
import matplotlib.pyplot as plt
o=cv2.imread("./img/hand1.png")
plt.hist(o.ravel(),16)
plt.show()

使用OpenCV繪制直方圖

OpenCV提供瞭函數cv2.calcHist()用來計算圖像的統計直方圖,該函數能統計各個灰度級的像素點個數。利用matplotlib.pyplot模塊中的plot()函數,可以將函數cv2.calcHist()的統計結果繪制成直方圖。

  • 用cv2.calcHist()函數統計圖像直方圖信息

函數cv2.calcHist()用於統計圖像直方圖信息,其語法格式為:

hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )

函數中返回值及參數的含義為:

  • hist:返回的統計直方圖,是一個一維數組,數組內的元素是各個灰度級的像素個數。
  • images:原始圖像,該圖像需要使用“[ ]”括起來。
  • channels:指定通道編號。通道編號需要用“[ ]”括起來,如果輸入圖像是單通道灰度圖像,該參數的值就是[0]。對於彩色圖像,它的值可以是[0]、[1]、[2],分別對應通道B、G、R。
  • mask:掩模圖像。當統計整幅圖像的直方圖時,將這個值設為None。當統計圖像某一部分的直方圖時,需要用到掩模圖像。

僅計算掩膜區域

  • histSize:BINS的值,該值需要用“[ ]”括起來。例如,BINS的值是256,需要使用“[256]”作為此參數值。
  • ranges:即像素值范圍。例如,8位灰度圖像的像素值范圍是[0, 255]。
  • accumulate:累計(累積、疊加)標識,默認值為False。如果被設置為True,則直方圖在開始計算時不會被清零,計算的是多個直方圖的累積結果,用於對一組圖像計算直方圖。該參數允許從多個對象中計算單個直方圖,或者實時更新直方圖。該參數是可選的,一般情況下不需要設置。

**例子:**使用cv2.calcHist()函數計算一幅圖像的統計直方圖結果,並觀察得到的統計直方圖信息。

import cv2
import numpy as np
img=cv2.imread("./img/hand1.png")
hist = cv2.calcHist([img], [0], None, [256], [0,255])
print(type(hist))
print(hist.shape)
print(hist.size)
print(hist)

######
<class 'numpy.ndarray'>
(256, 1)
256
[[  88.]
 [  31.]
 [  48.]
 [  66.]
 ...

函數cv2.calcHist()返回值的數據類型為“ndarray”。該數據的shape為(256,1),說明其有256行1列。

該數據的size為256,說明有256個元素,分別對應著256個灰度級在圖像內出現的次數。

plot()函數的使用:

使用matplotlib.pyplot模塊內的plot()函數,可以將函數cv2.calcHist()的返回值繪制為圖像直方圖。

繪制統計直方圖:

使用函數plot()將函數cv2.calcHist()的返回值繪制為直方圖。

import cv2
import matplotlib.pyplot as plt
o=cv2.imread(&quot;./img/hand1.png&quot;)
histb = cv2.calcHist([o], [0], None, [256], [0,255])
plt.plot(histb, color='b')
plt.show()

使用函數plot()和函數cv2.calcHist(),將彩色圖像各個通道的直方圖繪制在一個窗口內。

import cv2
import matplotlib.pyplot as plt
o=cv2.imread(&quot;./img/hand1.png&quot;)
histb = cv2.calcHist([o], [0], None, [256], [0,255])
histg = cv2.calcHist([o], [1], None, [256], [0,255])
histr = cv2.calcHist([o], [2], None, [256], [0,255])
plt.plot(histb, color='b')
plt.plot(histg, color='g')
plt.plot(histr, color='r')
plt.show()

使用掩模繪制直方圖

在函數cv2.calcHist()中,參數mask用於標識是否使用掩模圖像。

當使用掩模圖像獲取直方圖時,僅獲取掩模參數mask指定區域的直方圖。

  • 掩模處理的概念
    通常將掩模圖像白色區域的值設置為255,然後讓掩模圖像與原始圖像進行按位與運算
    OpenCV提供瞭bitwise_and函數,用於兩個像素值之間的按位與運算。
    掩模圖像的白色背景部分設置為255,黑色背景部分設置為0
    當在一個函數F中使用瞭掩模時,就意味著要先將參與運算的圖像與掩模圖像進行按位與運算,得到掩模運算結果。然後,再將掩模運算結果,作為函數F的參數完成函數F所指定的運算。
  • 構造掩模圖像
    在構造掩模圖像時,通常先構造一個像素值都是0的二維數組,再將數組中指定區域的像素值設定為255,就得到瞭掩模圖像。
    首先使用函數np.zeros()構造一個像素值都是0的二維數組,然後將其中間部分的值設置為255
import cv2
import numpy as np
mask=np.zeros([600,600], np.uint8)
mask[200:400,200:400]=255
cv2.imshow('mask', mask)
cv2.waitKey()
cv2.destroyAllWindows()

使用掩模繪制直方圖:

繪制掩模圖像時,首先將函數cv2.calcHist()的mask參數設置為掩模圖像,得到掩模處理的直方圖信息,再使用plot()函數完成直方圖的繪制。

函數cv2.calcHist()的語法格式:

hist&nbsp;=&nbsp;cv2.calcHist(&nbsp;images,&nbsp;channels,&nbsp;mask,&nbsp;histSize,&nbsp;ranges,&nbsp;accumulate&nbsp;)

其中,mask參數就是掩模圖像。

繪制掩模結果圖像的直方圖

首先構造一個掩模圖像,然後使用函數cv2.calcHist()計算掩模結果圖像的統計直方圖信息,最後使用函數plot()繪制掩模圖像的直方圖。

掩模圖像要保持與原始圖像相等的大小, 使用參數image.shape表示構造與原始圖像等大小的掩模圖像。

import&nbsp;cv2
import&nbsp;numpy&nbsp;as&nbsp;np
import&nbsp;matplotlib.pyplot&nbsp;as&nbsp;plt
image=cv2.imread(&quot;./img/hand1.png&quot;,&nbsp;cv2.IMREAD_GRAYSCALE)
mask=np.zeros(image.shape,&nbsp;np.uint8)
mask[200:400,200:400]=255
histImage=cv2.calcHist([image],&nbsp;[0],&nbsp;None,&nbsp;[256],&nbsp;[0,255])
histMI=cv2.calcHist([image],&nbsp;[0],&nbsp;mask,&nbsp;[256],&nbsp;[0,255])
plt.plot(histImage,color=&quot;b&quot;)
plt.plot(histMI,color=&quot;g&quot;)
plt.show()

直方圖均衡化

如果一幅圖像擁有全部可能的灰度級,並且像素值的灰度均勻分佈,那麼這幅圖像就具有高對比度和多變的灰度色調,灰度級豐富且覆蓋范圍較大。

在外觀上,這樣的圖像具有更豐富的色彩,不會過暗或過亮。直方圖均衡化的主要目的是將原始圖像的灰度級均勻地映射到整個灰度級范圍內,得到一個灰度級分佈均勻的圖像。這種均衡化,既實現瞭灰度值統計上的概率均衡,也實現瞭人類視覺系統(Human Visual System, HVS)上的視覺均衡。

直方圖均衡化原理

直方圖均衡化的算法主要包括兩個步驟:

  • 計算累計直方圖。
  • 對累計直方圖進行區間轉換

在此基礎上,再利用人眼視覺達到直方圖均衡化的目的。

在累計直方圖的基礎上,對原有灰度級空間進行轉換。可以在原有范圍內對灰度級實現均衡化,也可以在更廣泛的灰度空間范圍內對灰度級實現均衡化。

在原有范圍內實現均衡化

用當前灰度級的累計概率乘以當前灰度級的最大值,得到新的灰度級,並作為均衡化的結果。

在更廣泛的范圍內實現均衡化

用當前灰度級的累計概率乘以更廣泛范圍灰度級的最大值,得到新的灰度級,並作為均衡化的結果。

通過如下兩個步驟,可以讓直方圖達到均衡化的效果。

  • 計算累計直方圖。
  • 將累計直方圖進行區間轉換。

直方圖均衡化使圖像色彩更均衡、外觀更清晰,也使圖像更便於處理,它被廣泛地應用在醫學圖像處理、車牌識別、人臉識別等領域。

直方圖均衡化處理

OpenCV使用函數cv2.equalizeHist()實現直方圖均衡化。

該函數的語法格式為:

dst&nbsp;=&nbsp;cv2.equalizeHist(&nbsp;src&nbsp;)

  • src是8位單通道原始圖像
  • dst是直方圖均衡化處理的結果

例子: 使用函數cv2.equalizeHist()實現直方圖均衡化

#-----------導入使用的模塊--------------- 
import&nbsp;cv2
import&nbsp;matplotlib.pyplot&nbsp;as&nbsp;plt
#-----------讀取原始圖像--------------- 
img&nbsp;=&nbsp;cv2.imread('./img/hand1.png', cv2.IMREAD_GRAYSCALE)
#-----------直方圖均衡化處理--------------- 
equ&nbsp;=&nbsp;cv2.equalizeHist(img)
#-----------顯示均衡化前後的圖像--------------- 
cv2.imshow(&quot;original&quot;,&nbsp;img)
cv2.imshow(&quot;result&quot;,&nbsp;equ)
#-----------顯示均衡化前後的直方圖--------------- 
plt.figure(&quot;原始圖像直方圖&quot;)&nbsp;&nbsp;&nbsp;#構建窗口 
plt.hist(img.ravel(),256)
plt.figure(&quot;均衡化結果直方圖&quot;)&nbsp;&nbsp;#構建新窗口 
plt.hist(equ.ravel(),256)
plt.show()
#----------等待釋放窗口--------------------- 
cv2.waitKey()
cv2.destroyAllWindows()

語句“plt.figure("原始圖像直方圖")”用於構造名為“原始圖像直方圖”的新窗口。

均衡化是指綜合考慮瞭統計概率和HVS的均衡化結果。

pyplot 模塊介紹

matplotlib.pyplot模塊提供瞭一個類似於MATLAB繪圖方式的框架,可以使用其中的函數方便地繪制圖形。

subplot 函數

模塊matplotlib.pyplot提供瞭函數matplotlib.pyplot.subplot()用來向當前窗口內添加一個子窗口對象。該函數的語法格式為:

matplotlib.pyplot.subplot(nrows,&nbsp;ncols,&nbsp;index)
  • nrows為行數。
  • ncols為列數。
  • index為窗口序號。

序號是從“1”開始而不是從“0”開始的。

如果所有參數都小於10,可以省略彼此之間的逗號,直接寫三個數字。例如,subplot(2, 3, 4)可以直接表示為subplot(234)。

import&nbsp;cv2
import&nbsp;matplotlib.pyplot&nbsp;as&nbsp;plt
img&nbsp;=&nbsp;cv2.imread('./img/hand1.png', cv2.IMREAD_GRAYSCALE)
equ&nbsp;=&nbsp;cv2.equalizeHist(img)
plt.figure(&quot;subplot示例&quot;)
plt.subplot(121),&nbsp;plt.hist(img.ravel(),256)
plt.subplot(122),&nbsp;plt.hist(equ.ravel(),256)
plt.show()

imshow函數

模塊matplotlib.pyplot提供瞭函數matplotlib.pyplot.imshow()用來顯示圖像。

其語法格式為:

matplotlib.pyplot.imshow(X,&nbsp;cmap=None)

  • X為圖像信息,可以是各種形式的數值。
  • cmap表示色彩空間。該值是可選項,默認值為null,默認使用RGB(A)色彩空間。

使用函數matplotlib.pyplot.imshow()顯示彩色圖像

import&nbsp;cv2
import&nbsp;matplotlib.pyplot&nbsp;as&nbsp;plt
img&nbsp;=&nbsp;cv2.imread('./img/hand1.png')
imgRGB=cv2.cvtColor(img,&nbsp;cv2.COLOR_BGR2RGB)
plt.figure(&quot;顯示結果&quot;)
plt.subplot(121)
plt.imshow(img),&nbsp;plt.axis('off')
plt.subplot(122)
plt.imshow(imgRGB),&nbsp;plt.axis('off')
plt.show()
  • 語句“plt.axis('off')”表示關閉坐標軸的顯示

使用函數matplotlib.pyplot.imshow()顯示灰度圖像。

嘗試使用不同的形式顯示灰度圖像

import cv2
import matplotlib.pyplot as plt
o = cv2.imread('./img/hand1.png')
g=cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
plt.figure(&quot;灰度圖像顯示演示&quot;)
plt.subplot(221)
plt.imshow(o), plt.axis('off')
plt.subplot(222)
plt.imshow(o, cmap=plt.cm.gray), plt.axis('off')
plt.subplot(223)
plt.imshow(g), plt.axis('off')
plt.subplot(224)
plt.imshow(g, cmap=plt.cm.gray), plt.axis('off')
plt.show()

隻有使用灰度圖像作為參數,並且將色彩空間參數值設置為“cmap=plt.cm.gray”,灰度圖像才被正常顯示。

使用函數matplotlib.pyplot.imshow()以不同的參數形式顯示灰度圖像。

import cv2
import matplotlib.pyplot as plt
o = cv2.imread('./img/hand1.png')
g=cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
plt.figure(&quot;灰度圖像顯示演示&quot;)
plt.subplot(221); plt.imshow(g, cmap=plt.cm.gray)
plt.subplot(222); plt.imshow(g, cmap=plt.cm.gray_r)
plt.subplot(223); plt.imshow(g, cmap='gray')
plt.subplot(224); plt.imshow(g, cmap='gray_r')
plt.show()

色彩空間參數cmap的參數值“plt.cm.gray_r”及“gray_r”中的“r”是英文“reverse”的縮寫,表示逆轉的意思。

到此這篇關於python中opencv 直方圖處理的文章就介紹到這瞭,更多相關python opencv 內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: