国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

Python OpenCV 直方圖的計算與顯示的方法示例

2020-01-04 15:55:09
字體:
供稿:網(wǎng)友

本篇文章介紹如何用OpenCV Python來計算直方圖,并簡略介紹用NumPy和Matplotlib計算和繪制直方圖

直方圖的背景知識、用途什么的就直接略過去了。這里直接介紹方法。

計算并顯示直方圖

與C++中一樣,在Python中調(diào)用的OpenCV直方圖計算函數(shù)為cv2.calcHist。

cv2.calcHist的原型為:

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

通過一個例子來了解其中的各個參數(shù):

#coding=utf-8 import cv2 import numpy as np  image = cv2.imread("D:/histTest.jpg", 0) hist = cv2.calcHist([image],   [0], #使用的通道   None, #沒有使用mask   [256], #HistSize   [0.0,255.0]) #直方圖柱的范圍 

其中第一個參數(shù)必須用方括號括起來。

第二個參數(shù)是用于計算直方圖的通道,這里使用灰度圖計算直方圖,所以就直接使用第一個通道;

第三個參數(shù)是Mask,這里沒有使用,所以用None。

第四個參數(shù)是histSize,表示這個直方圖分成多少份(即多少個直方柱)。第二個例子將繪出直方圖,到時候會清楚一點。

第五個參數(shù)是表示直方圖中各個像素的值,[0.0, 256.0]表示直方圖能表示像素值從0.0到256的像素。

最后是兩個可選參數(shù),由于直方圖作為函數(shù)結(jié)果返回了,所以第六個hist就沒有意義了(待確定)

最后一個accumulate是一個布爾值,用來表示直方圖是否疊加。

彩色圖像不同通道的直方圖

下面來看下彩色圖像的直方圖處理。以最著名的lena.jpg為例,首先讀取并分離各通道:

import cv2   import numpy as np      img = cv2.imread("D:/lena.jpg")   b, g, r = cv2.split(img) 

接著計算每個通道的直方圖,這里將其封裝成一個函數(shù):

def calcAndDrawHist(image, color):    hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])    minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)    histImg = np.zeros([256,256,3], np.uint8)    hpt = int(0.9* 256);        for h in range(256):      intensity = int(hist[h]*hpt/maxVal)      cv2.line(histImg,(h,256), (h,256-intensity), color)          return histImg;  

這里只是之前代碼的簡單封裝,所以注釋就省掉了。

接著在主函數(shù)中使用:

if __name__ == '__main__':    img = cv2.imread("D:/lena.jpg")    b, g, r = cv2.split(img)      histImgB = calcAndDrawHist(b, [255, 0, 0])    histImgG = calcAndDrawHist(g, [0, 255, 0])    histImgR = calcAndDrawHist(r, [0, 0, 255])        cv2.imshow("histImgB", histImgB)    cv2.imshow("histImgG", histImgG)    cv2.imshow("histImgR", histImgR)    cv2.imshow("Img", img)    cv2.waitKey(0)    cv2.destroyAllWindows()  

這樣就能得到三個通道的直方圖了,如下:

python,計算直方圖,opencv

更進一步

這樣做有點繁瑣,參考abid rahman的做法,無需分離通道,用折線來描繪直方圖的邊界可在一副圖中同時繪制三個通道的直方圖。方法如下:

#coding=utf-8  import cv2  import numpy as np       img = cv2.imread('D:/lena.jpg')  h = np.zeros((256,256,3)) #創(chuàng)建用于繪制直方圖的全0圖像       bins = np.arange(256).reshape(256,1) #直方圖中各bin的頂點位置  color = [ (255,0,0),(0,255,0),(0,0,255) ] #BGR三種顏色  for ch, col in enumerate(color):    originHist = cv2.calcHist([img],[ch],None,[256],[0,256])    cv2.normalize(originHist, originHist,0,255*0.9,cv2.NORM_MINMAX)    hist=np.int32(np.around(originHist))    pts = np.column_stack((bins,hist))    cv2.polylines(h,[pts],False,col)       h=np.flipud(h)       cv2.imshow('colorhist',h)  cv2.waitKey(0)  

結(jié)果如下圖所示:

python,計算直方圖,opencv

代碼說明:

這里的for循環(huán)是對三個通道遍歷一次,每次繪制相應(yīng)通道的直方圖的折線。for循環(huán)的第一行是計算對應(yīng)通道的直方圖,經(jīng)過上面的介紹,應(yīng)該很容易就能明白。

這里所不同的是沒有手動的計算直方圖的最大值再乘以一個系數(shù),而是直接調(diào)用了OpenCV的歸一化函數(shù)。該函數(shù)將直方圖的范圍限定在0-255×0.9之間,與之前的一樣。下面的hist= np.int32(np.around(originHist))先將生成的原始直方圖中的每個元素四舍六入五湊偶取整(cv2.calcHist函數(shù)得到的是float32類型的數(shù)組),接著將整數(shù)部分轉(zhuǎn)成np.int32類型。即61.123先轉(zhuǎn)成61.0,再轉(zhuǎn)成61。注意,這里必須使用np.int32(...)進行轉(zhuǎn)換,numpy的轉(zhuǎn)換函數(shù)可以對數(shù)組中的每個元素都進行轉(zhuǎn)換,而Python的int(...)只能轉(zhuǎn)換一個元素,如果使用int(...),將導(dǎo)致only length-1 arrays can be converted to Python scalars錯誤。

下面的pts = np.column_stack((bins,hist))是將直方圖中每個bin的值轉(zhuǎn)成相應(yīng)的坐標(biāo)。比如hist[0] =3,...,hist[126] = 178,...,hist[255] = 5;而bins的值為[[0],[1],[2]...,[255]]。使用np.column_stack將其組合成[0, 3]、[126, 178]、[255, 5]這樣的坐標(biāo)作為元素組成的數(shù)組。

最后使用cv2.polylines函數(shù)根據(jù)這些點繪制出折線,第三個False參數(shù)指出這個折線不需要閉合。第四個參數(shù)指定了折線的顏色。

當(dāng)所有完成后,別忘了用h = np.flipud(h)反轉(zhuǎn)繪制好的直方圖,因為繪制時,[0,0]在圖像的左上角。這在直方圖可視化一節(jié)中有說明。

NumPy版的直方圖計算

在查閱abid rahman的資料時,發(fā)現(xiàn)他用NumPy的直方圖計算函數(shù)np.histogram也實現(xiàn)了相同的效果。如下:

#coding=utf-8 import cv2 import numpy as np  img = cv2.imread('D:/lena.jpg') h = np.zeros((300,256,3)) bins = np.arange(257) bin = bins[0:-1] color = [ (255,0,0),(0,255,0),(0,0,255) ]  for ch,col in enumerate(color):   item = img[:,:,ch]   N,bins = np.histogram(item,bins)   v=N.max()   N = np.int32(np.around((N*255)/v))   N=N.reshape(256,1)   pts = np.column_stack((bin,N))   cv2.polylines(h,[pts],False,col)  h=np.flipud(h)  cv2.imshow('img',h) cv2.waitKey(0) 

效果圖和上面的一個相同。NumPy的histogram函數(shù)將在NumPy通用函數(shù)這篇博文中介紹,這里就不詳細解釋了。這里采用的是與一開始相同的比例系數(shù)的方法,參考本文的第二節(jié)。

另外,通過NumPy和matplotlib可以更方便的繪制出直方圖,下面的代碼供大家參考,如果有機會,再寫的專門介紹matplotlib的文章。

import matplotlib.pyplot as plt import numpy as np import cv2  img = cv2.imread('D:/lena.jpg') bins = np.arange(257)  item = img[:,:,1] hist,bins = np.histogram(item,bins) width = 0.7*(bins[1]-bins[0]) center = (bins[:-1]+bins[1:])/2 plt.bar(center, hist, align = 'center', width = width) plt.show() 

python,計算直方圖,opencv

這里顯示的是綠色通道的直方圖。

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持VEVB武林網(wǎng)。


注:相關(guān)教程知識閱讀請移步到python教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 林周县| 邮箱| 务川| 临朐县| 阿鲁科尔沁旗| 离岛区| 盐源县| 阿克陶县| 麻城市| 陆川县| 翁牛特旗| 嵩明县| 商南县| 陆良县| 枞阳县| 佛学| 丹棱县| 壤塘县| 盘锦市| 隆德县| 庆安县| 陇南市| 无为县| 信丰县| 安宁市| 石阡县| 勐海县| 南丰县| 铜山县| 霍州市| 武安市| 清苑县| 扶风县| 曲水县| 石楼县| 金沙县| 长阳| 界首市| 桂阳县| 华池县| 河北省|