首頁 > 軟體

python中opencv 直方圖處理

2022-06-01 18:00:30

直方圖處理

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

直方圖的含義

直方圖是影象內灰度值的統計特性與影象灰度值之間的函數,直方圖統計影象內各個灰度級出現的次數。從直方圖的圖形上觀察,橫座標是影象中各畫素點的灰度級,縱座標是具有該灰度級(畫素值)的畫素個數。在繪製直方圖時,將灰度級作為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 &#39;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=&#39;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=&#39;b')
plt.plot(histg, color=&#39;g')
plt.plot(histr, color=&#39;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(&#39;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(&#39;./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(&#39;./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(&#39;./img/hand1.png')
imgRGB=cv2.cvtColor(img,&nbsp;cv2.COLOR_BGR2RGB)
plt.figure(&quot;顯示結果&quot;)
plt.subplot(121)
plt.imshow(img),&nbsp;plt.axis(&#39;off')
plt.subplot(122)
plt.imshow(imgRGB),&nbsp;plt.axis(&#39;off')
plt.show()
  • 語句“plt.axis('off')”表示關閉座標軸的顯示

使用函數matplotlib.pyplot.imshow()顯示灰度影象。

嘗試使用不同的形式顯示灰度影象

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

只有使用灰度影象作為引數,並且將色彩空間引數值設定為“cmap=plt.cm.gray”,灰度影象才被正常顯示。

使用函數matplotlib.pyplot.imshow()以不同的引數形式顯示灰度影象。

import cv2
import matplotlib.pyplot as plt
o = cv2.imread(&#39;./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=&#39;gray')
plt.subplot(224); plt.imshow(g, cmap=&#39;gray_r')
plt.show()

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

到此這篇關於python中opencv 直方圖處理的文章就介紹到這了,更多相關python opencv 內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com