1. 程式人生 > >OpenCV Python教程(3)(4)(5): 直方圖的計算與顯示 形態學處理 初級濾波內

OpenCV Python教程(3)(4)(5): 直方圖的計算與顯示 形態學處理 初級濾波內

OpenCV Python教程(3、直方圖的計算與顯示)

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

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

計算並顯示直方圖

與C++中一樣,在Python中呼叫的OpenCV直方圖計算函式為cv2.calcHist。

cv2.calcHist的原型為:

  1. cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) #返回hist
通過一個例子來了解其中的各個引數:
  1. #coding=utf-8
  2. import cv2  
  3. import numpy as np  
  4. image = cv2.imread("D:/histTest.jpg"0)  
  5. hist = cv2.calcHist([image],  
  6.     [0], #使用的通道
  7.     None#沒有使用mask
  8.     [256], #HistSize
  9.     [0.0,255.0]) #直方圖柱的範圍
其中第一個引數必須用方括號括起來。

第二個引數是用於計算直方圖的通道,這裡使用灰度圖計算直方圖,所以就直接使用第一個通道;

第三個引數是Mask,這裡沒有使用,所以用None。

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

第五個引數是表示直方圖中各個畫素的值,[0.0, 256.0]表示直方圖能表示畫素值從0.0到256的畫素。

最後是兩個可選引數,由於直方圖作為函式結果返回了,所以第六個hist就沒有意義了(待確定)

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

彩色影象不同通道的直方圖

彩色影象不同通道的直方圖

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

  1. import cv2      
  2. import numpy as np      
  3. img = cv2.imread("D:/lena.jpg")      
  4. b, g, r = cv2.split(img)   
接著計算每個通道的直方圖,這裡將其封裝成一個函式:
  1. def calcAndDrawHist(image, color):    
  2.     hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])    
  3.     minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)    
  4.     histImg = np.zeros([256,256,3], np.uint8)    
  5.     hpt = int(0.9256);    
  6.     for h in range(256):    
  7.         intensity = int(hist[h]*hpt/maxVal)    
  8.         cv2.line(histImg,(h,256), (h,256-intensity), color)    
  9.     return histImg;   
這裡只是之前程式碼的簡單封裝,所以註釋就省掉了。

接著在主函式中使用:

  1. if __name__ == '__main__':    
  2.     img = cv2.imread("D:/lena.jpg")    
  3.     b, g, r = cv2.split(img)    
  4.     histImgB = calcAndDrawHist(b, [25500])    
  5.     histImgG = calcAndDrawHist(g, [02550])    
  6.     histImgR = calcAndDrawHist(r, [00255])    
  7.     cv2.imshow("histImgB", histImgB)    
  8.     cv2.imshow("histImgG", histImgG)    
  9.     cv2.imshow("histImgR", histImgR)    
  10.     cv2.imshow("Img", img)    
  11.     cv2.waitKey(0)    
  12.     cv2.destroyAllWindows()   
這樣就能得到三個通道的直方圖了,如下:

更進一步

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

  1. #coding=utf-8  
  2. import cv2    
  3. import numpy as np    
  4. img = cv2.imread('D:/lena.jpg')    
  5. h = np.zeros((256,256,3)) #建立用於繪製直方圖的全0影象  
  6. bins = np.arange(256).reshape(256,1#直方圖中各bin的頂點位置  
  7. color = [ (255,0,0),(0,255,0),(0,0,255) ] #BGR三種顏色  
  8. for ch, col in enumerate(color):    
  9.     originHist = cv2.calcHist([img],[ch],None,[256],[0,256])    
  10.     cv2.normalize(originHist, originHist,0,255*0.9,cv2.NORM_MINMAX)    
  11.     hist=np.int32(np.around(originHist))    
  12.     pts = np.column_stack((bins,hist))    
  13.     cv2.polylines(h,[pts],False,col)    
  14. h=np.flipud(h)    
  15. cv2.imshow('colorhist',h)    
  16. cv2.waitKey(0)    
結果如下圖所示:


程式碼說明:

這裡的for迴圈是對三個通道遍歷一次,每次繪製相應通道的直方圖的折線。for迴圈的第一行是計算對應通道的直方圖,經過上面的介紹,應該很容易就能明白。

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

下面的pts = np.column_stack((bins,hist))是將直方圖中每個bin的值轉成相應的座標。比如hist[0] =3,...,hist[126] = 178,...,hist[255] = 5;而bins的值為[[0],[1],[2]...,[255]]。使用np.column_stack將其組合成[0, 3]、[126, 178]、[255, 5]這樣的座標作為元素組成的陣列。

最後使用cv2.polylines函式根據這些點繪製出折線,第三個False引數指出這個折線不需要閉合。第四個引數指定了折線的顏色。

當所有完成後,別忘了用h = np.flipud(h)反轉繪製好的直方圖,因為繪製時,[0,0]在影象的左上角。這在直方圖視覺化一節中有說明。

NumPy版的直方圖計算

在查閱abid rahman的資料時,發現他用NumPy的直方圖計算函式np.histogram也實現了相同的效果。如下:

  1. #coding=utf-8
  2. import cv2  
  3. import numpy as np  
  4. img = cv2.imread('D:/lena.jpg')  
  5. h = np.zeros((300,256,3))  
  6. bins = np.arange(257)  
  7. bin = bins[0:-1]  
  8. color = [ (255,0,0),(0,255,0),(0,0,255) ]  
  9. for ch,col in enumerate(color):  
  10.     item = img[:,:,ch]  
  11.     N,bins = np.histogram(item,bins)  
  12.     v=N.max()  
  13.     N = np.int32(np.around((N*255)/v))  
  14.     N=N.reshape(256,1)  
  15.     pts = np.column_stack((bin,N))  
  16.     cv2.polylines(h,[pts],False,col)  
  17. h=np.flipud(h)  
  18. cv2.imshow('img',h)  
  19. cv2.waitKey(0)  
效果圖和上面的一個相同。NumPy的histogram函式將在NumPy通用函式這篇博文中介紹,這裡就不詳細解釋了。這裡採用的是與一開始相同的比例係數的方法,參考本文的第二節。

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

  1. import matplotlib.pyplot as plt  
  2. import numpy as np  
  3. import cv2  
  4. img = cv2.imread('D:/lena.jpg')  
  5. bins = np.arange(257)  
  6. item = img[:,:,1]  
  7. hist,bins = np.histogram(item,bins)  
  8. width = 0.7*(bins[1]-bins[0])  
  9. 相關推薦

    OpenCV Python教程345 直方圖計算顯示 形態學處理 初級濾波

    OpenCV Python教程(3、直方圖的計算與顯示) 本篇文章介紹如何用OpenCV Python來計算直方圖,並簡略介紹用NumPy和Matplotlib計算和繪製直方圖 直方圖的背景知識、用途什麼的就直接略過去了。這裡直接介紹方法。 計算並顯

    泛型 Java語言程式設計 第十九章19.1、19.2、19.3、19.4、19.5

    程式小白,希望和大家多交流,共同學習 19.1 //使用陣列實現棧,當陣列滿的時候,自動建立一個更大的陣列 import java.util.Arrays; public class Array

    Python OpenCV _2直方圖計算顯示的四種方式

    此係列原始碼在我的GitHub裡:https://github.com/yeyujujishou19/Python-OpenCV 原圖 一,CV2分通道描繪直方圖:  import cv2 import numpy as np #計算並繪製直方圖 def calcAnd

    OpenCV-Python教程11、輪廓檢測

    相比C++而言,Python適合做原型。本系列的文章介紹如何在Python中用OpenCV圖形庫,以及與C++呼叫相應OpenCV函式的不同之處。這篇文章介紹在Python中使用OpenCV檢測並繪製輪廓。 提示: 轉載請詳細註明原作者及出處,謝謝!本文介紹在OpenCV

    OpenCV-Python教程7、Laplacian運算元

    本篇文章介紹如何用OpenCV-Python來使用Laplacian運算元。 提示: 轉載請詳細註明原作者及出處,謝謝!本文介紹使用在OpenCV-Python中使用Laplacian函式本文不介詳細的理論知識,讀者可從其他資料中獲取相應的背景知識。筆者推薦清華大學出版社的

    OpenCV-Python教程91011 使用霍夫變換檢測直線 直方圖均衡化 輪廓檢測

    OpenCV-Python教程(9、使用霍夫變換檢測直線) 相比C++而言,Python適合做原型。本系列的文章介紹如何在Python中用OpenCV圖形庫,以及與C++呼叫相應OpenCV函式的不同之處。這篇文章介紹在Python中使用OpenCV的霍夫變換檢

    OpenCV Python教程1、影象的載入、顯示和儲存

    轉載請詳細註明原作者及出處,謝謝! 本文是OpenCV  2 Computer Vision Application Programming Cookbook讀書筆記的第一篇。在筆記中將以Python語言改寫每章的程式碼。 PythonOpenCV的配置這裡就不介紹了。 注

    基於輪廓提取影象文字2---OpenCV-Python教程11、輪廓檢測

    https://blog.csdn.net/sunny2038/article/details/12889059相比C++而言,Python適合做原型。本系列的文章介紹如何在Python中用OpenCV圖形庫,以及與C++呼叫相應OpenCV函式的不同之處。這篇文章介紹在Py

    Java學習不走彎路教程3.從文件內容查詢開始

    輔助 pass 多說 font sys sta case index exe 一. 前言在前兩章教程中,分別介紹了DOS環境搭建和Eclipse環境搭建。本章將帶大家實現用簡單SQL語句查詢文件。註:1.本文針對初學Java的同學訓練學習思路,請不要太糾結於細節問題。2.本

    Opencv Python版學習筆記 字元識別-分類器SVM,KNearest,RTrees,Boost,MLP

    Opencv提供了幾種分類器,例程裡通過字元識別來進行說明的 1、支援向量機(SVM):給定訓練樣本,支援向量機建立一個超平面作為決策平面,使得正例和反例之間的隔離邊緣被最大化。 函式原型:訓練原型 cv2.SVM.train(trainData, responses[, varIdx[,

    20151117 Linux下磁碟管理centos 6.51.新增硬碟 2.硬碟分割槽 3.格式化硬碟 4.掛載硬碟 5.設定開機自動掛載】

    Device contains neither a valid DOS partition table, nor Sun, SGI or OSF                               disklabel Building a new DOS disklabel with disk i

    Java語言程式設計 第十四章 14.1、14.2、14.3、14.4、12.5、14.6

    程式小白,希望和大家多交流,共同學習 因為沒有第十版的漢語電子書,(有的漢語版是第八版,使用的還是Swing)這部分內容只能使用英語版截圖。 14.1 //將image資料夾中的照片加載出來 import javafx.application.

    1.3.6.1.4.1SNMP-MIB庫

    iso.org.dod.internet.private.enterprises 最近在看SNMP,OID很好玩 1.3.6.1.4.1是Internet Assigned Numbers Authority (IANA)統一管理的,大家可以在http://www.iana.org/assignments/

    Ardupilot飛控log程式碼學習3.6版本飛控韌體

    目錄 文章目錄 目錄 摘要 1.官網資料學習 新增一個新的日誌訊息(Adding a new Log Message) 簡單的方法(The Easy Way) 複雜的方法(The Harder Way)

    【轉】Win10 64 位Tensorflow-gpu安裝VS2017+CUDA9.2+cuDNN7.1.4+python3.6.5

    原文連結:https://blog.csdn.net/wwtor/article/details/80603296 Tensorflow 入門系列的第一篇,Tensorflow-gpu的下載與安裝。CSDN上能搜到很多學習資料,對初學者非常有幫助。剛安裝了目前最新版本的Tensorflow,當然

    redis 叢集3.0版本開始支援叢集功能

    叢集簡介 Redis 叢集是一個可以在多個 Redis 節點之間進行資料共享的設施(installation)。 Redis 叢集不支援那些需要同時處理多個鍵的 Redis 命令, 因為執行這些命令需要在多個 Redis 節點之間移動資料, 並且在高負載的情況下, 這

    Java 9 揭祕3. 建立你的第一個模組

    文 by / 林本託 Tips 做一個終身學習的人。 在這個章節中,主要介紹以下內容: 如何編寫模組化的Java程式 如何編譯模組化程式 如何將模組的專案打包成模組化的JAR檔案 如何執行模組化程式 在本章中,將介紹如何使用模組 —— 從編寫原始碼到編譯,打包和執行程式。 本章分為兩部分。 第一部分

    vm 克隆虛擬機器xshell連線不上問題centos6.4、6.5

    克隆完成後,進入系統: 1. 檢查:selinux是否關閉,iptable是否關閉 2. 檢查ssh是否連線 3. ping 127.0.0.1 是否連線通 4. ifconfig -a 命令檢視結果    顯示的是eth1驅動,然後複製(或者記住)HWaddr地址後三個

    js中簡易選項卡的實現3種方法實現樣式的封裝

    清除浮動的三種方式 1.overflow: hidden; 清除子元素的浮動對父元素的影響 2.clear: both; 清除哥哥元素的浮動對弟弟元素的影響 3.:after{ display: block; content: “”; clear: bo

    【翻譯OpenCV-Python教程】坎尼邊緣檢測

    ⚠️由於自己的拖延症,3.4.3翻到一半,OpenCV釋出了4.0.0了正式版,所以接下來是按照4.0.0翻譯的。 ⚠️除了版本之外,其他還是照舊,Canny Edge Detection,附原文。 目標 在這一節,我們將學到: 坎尼邊緣檢測的概念