OpenCV Python 直方圖


OpenCV Python 直方圖


直方圖

什么是直方圖

直方圖的作用

敲程序

下面為使用PythonOpenCVmatplotlib來編寫幾個samples程序來實際感受一下圖像的直方圖:

使用matplotlib計算直方圖

代碼

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('~/Pictures/IMG_4137.JPG', 0)
plt.hist(img.ravel() , 256, [0, 256])
plt.show()

出現錯誤

上面的這段程序,你運行會出現這樣的error:

Traceback (most recent call last): File "/home/aobo/PycharmProjects/OpenCV2/Histograms/hist.py", line 6, in <module> plt.hist(img.ravel() , 256, [0, 256]) AttributeError: 'NoneType' object has no attribute 'ravel'

解決辦法

將代碼里的下面這行

img = cv2.imread('~/Pictures/IMG_4137.JPG', 0)

修改為:(圖片路徑使用完整的絕對路徑)

img = cv2.imread('/home/aobo/Pictures/IMG_4137.JPG', 0)

錯誤的原因是:img變量沒有成功的載入圖片(cv2.imread()),所以這個img變量就是一個沒有任何變量類型的一個變量,在Python語言里img現在就是一個NoneType對象。因為只要Mat對象才有ravel()這個方法,而NoneType對象沒有,所以才出現了上面的error

img.ravel() 將圖像轉成一維數組。

運行結果:

Figure 1


輸出一個彩色圖像的直方圖

代碼

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('/home/aobo/Pictures/IMG_4137.JPG')
color = ('b','g','r')
# enumerate():python里的一個新函數
# 它的作用:同時遍歷索引(i)和元素(col)
for i,col in enumerate(color):
    histr = cv2.calcHist([img], [i], None, [256], [0, 256])
    plt.plot(histr, color = col)
    plt.xlim([0, 256])
plt.show()

運行效果

Figure 1

代碼講解

histr = cv2.calcHist([img], [i], None, [256], [0, 256])

cv2.calcHist()是OpenCV里面求直方圖的函數。下面介紹這個函數需要傳入的形參:

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

實參 對應形參 解釋
[img] images 原始圖像,需要使用[]修飾
[i] channels cv2.calcHist()函數一次只能得到一張圖片的其中一個通道的直方圖,所以,這里傳入的是本次需要處理的元素圖片的通道的索引號,同樣需要使用[]修飾。如果輸入的元素圖像是灰度圖,它的值就是[0]; 如果輸入的元素圖像是彩色圖像的話,傳入的參數可以是[0], [1], [2],它們分別對應着通道B, G, R。
plt.plot(histr, color = col)

這句話中的col的值是:’b’, ‘g ’ 或 ‘r’,賦給color形參,函數會自動處理成形應的顏色值,用這個顏色值將histr直方圖繪制到plt畫板上。

plt.xlim([0, 256])

設置plt畫板x軸的上下限,就是x軸所顯示的長度。我們將這段代碼修改出下面這個樣子,然后運行程序,會得到下面的結果:

plt.xlim([0, 100])

Figure 1


使用掩模

代碼

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('/home/aobo/Pictures/IMG_4137.JPG')
color = ('b','g','r')

mask = np.zeros(img.shape[:2], np.uint8)
mask[1000:2000, 1000:2000] = 255
masked_img = cv2.bitwise_and(img, img, mask = mask)

hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])

plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])

plt.show()

運行效果

<注>:當原始圖像使用較大圖像的時候,你會發現程序運行后需要好久才能得到下面的結果。
Figure 1

代碼解釋

mask = np.zeros(img.shape[:2], np.uint8)
mask[1000:2000, 1000:2000] = 255

制作一個掩模。首先使用np.zeros()函數創建一個與原圖尺寸和深度都一樣,像素值全為0(黑色)圖像mask,然后指定mask掩模的[1000:2000, 1000:2000]區域的像素全為255(白色)。上圖右上角的圖就是掩模圖像。

masked_img = cv2.bitwise_and(img, img, mask = mask)

現在掩模發揮了作用:掩模的黑色區域(像素值為0)用來遮蓋原圖img,即不參與圖像處理,只保留像素值不為0的區域。masked_img圖像就是上圖左下角的圖像。
cv2.bitwise_and()函數的功能是位與。下面是這個函數的聲明:

cv2.bitwise_and(src1, src2[, dst[, mask]])

當前代碼里,對應的src1src2是同一種數據類型,所以此時cv2.bitwise_and()函數執行的是下面的操作:
Alt text

hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])

分別計算出原圖img的直方圖和img掩模區域的直方圖。

plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])

subplot()matplotlib.pyplot里的函數。它是:將多個圖畫到一個平面上的工具。

subplot(m, n, p) 或者subplot(mnp)

m 表示圖排成m行
n 表示圖排成n列
p 表示將圖畫到Figure(指的是上面截圖里的窗口)哪個圖上,順序是從左到右,從上到下


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM