OpenCV里的imshow()和Matplotlib.pyplot的imshow()的實(shí)現(xiàn)
一、問題
在Python里使用OpenCV時(shí),一般是通過cv2.imread讀入圖片,然后用plt.imshow顯示圖片,但最近學(xué)習(xí)OpenCV時(shí)這樣做的結(jié)果與預(yù)期的結(jié)果有較大的出入。查找資料后,才明白OpenCV里的imshow()和Matplotlib.pyplot的imshow()在使用上有一些區(qū)別,不注意的話很容易就會(huì)導(dǎo)致很奇怪的結(jié)果。
下面的示例代碼及運(yùn)行結(jié)果顯示了這種差異:
import cv2 import matplotlib.pyplot as plt #以灰度模式讀入圖片 messi=cv2.imread('messi.jpg',0) #使用matplotlib.pyplot的imshow顯示圖片 plt.imshow(messi),plt.title('messi_plt') plt.xticks([]),plt.yticks([]) #隱藏坐標(biāo)軸 plt.show() #使用opencv的imshow顯示圖片 cv2.imshow('messi_cv',messi) cv2.waitKey(0) cv2.destroyAllWindows()
運(yùn)行結(jié)果如下:
左邊是原圖,中間是cv2.imshow的顯示結(jié)果,右邊是plt.imshow的顯示結(jié)果。很明顯地看到,明明是讀入灰度圖,plt.imshow的結(jié)果卻更像是張彩圖,這顯然是有問題的。
二、分析和解決辦法
為了比較和分析OpenCV里imshow()和Matplotlib.pyplot里imshow()這兩者的差異,下面分別對(duì)顯示彩圖以及顯示灰度圖這兩種情況來進(jìn)行說明。
彩色圖
對(duì)于彩色圖片,一般由R,G,B三個(gè)通道構(gòu)成。然而,需要注意的是,OpenCV里彩色圖片加載時(shí)是按照BGR的順序,Matplotlib里彩色圖片加載時(shí)是按照RGB的順序。所以,當(dāng)我們用cv2.imread讀入圖片,用cv2.imshow來顯示時(shí)自然是不會(huì)出問題的,但若用plt.imshow來顯示就會(huì)出現(xiàn)問題,如下面的結(jié)果所示。
這里省略示例代碼(和上面的幾乎相同,只是不要在cv2.imread里設(shè)置“0”這個(gè)參數(shù)即可),運(yùn)行結(jié)果如下:
左邊是原圖,中間是cv2.imshow的顯示結(jié)果,右邊是plt.imshow的顯示結(jié)果。顯然,plt.imshow的結(jié)果出現(xiàn)了問題。
為了解決這個(gè)問題,方法很簡單,就是將通道R和通道B的內(nèi)容調(diào)換一下,再用plt.imshow顯示時(shí)就正常了。下面給出該方法的示例代碼:
import cv2 import matplotlib.pyplot as plt #讀入彩色圖片 messi=cv2.imread('messi.jpg',1) #使用matplotlib.pyplot的imshow顯示圖片 plt.imshow(messi),plt.title('messi_plt') plt.xticks([]),plt.yticks([]) #隱藏坐標(biāo)軸 plt.show() ##調(diào)換r、b通道,生成rgb順序的圖片并顯示 b,g,r=cv2.split(messi) #通道的拆分 messi_rgb=cv2.merge((r,g,b)) #通道的融合 plt.imshow(messi_rgb),plt.title('messi_rgb_plt') plt.xticks([]),plt.yticks([]) plt.show() #使用opencv的imshow顯示圖片 cv2.imshow('messi_cv',messi) cv2.waitKey(0) cv2.destroyAllWindows()
灰度圖
灰度圖是單通道圖片,按理說不會(huì)出現(xiàn)上面彩色圖的那種問題,不管是用cv2.imshow顯示還是用plt.imshow顯示,結(jié)果都應(yīng)該是一樣的。然而,事實(shí)卻并非如此(如最開始的示例所示)。我糾結(jié)了好久不知道原因是什么,一開始以為是opencv和matplotlib的版本不匹配,結(jié)果更新版本之后還是有這個(gè)問題。后來,去找來matplotlib的API文檔才明白是咋回事。
matplotlib.pyplot.imshow函數(shù)里,有一個(gè)參數(shù)是cmap,API文檔里給出的說明是:
cmap : str or Colormap, optional
The Colormap instance or registered colormap name used to map scalar data to colors. This parameter is ignored for RGB(A) data. Defaults to rcParams[“image.cmap”] = ‘viridis'.
大致的意思是說,cmap給出了標(biāo)量值如何映射到顏色空間,并且對(duì)于RGB(A)圖像此參數(shù)是忽略的;默認(rèn)參數(shù)可查看rcParams[“image.cmap”]
。鏈接轉(zhuǎn)過去的文檔是matplotlib的示例配置文檔matplotlibrc,里面定義了各種變量的默認(rèn)值(這也是為什么我們?cè)谡{(diào)用matplotlib里的函數(shù)時(shí),有些參數(shù)我們沒給值也能正常運(yùn)行的原因)。在這里能看到,cmap的默認(rèn)值是viridis,這也就說明了在使用plt.imshow顯示灰度圖時(shí)出現(xiàn)問題的原因。
因此,為了解決該問題,使plt.imshow能正常地顯示灰度圖,方法也很簡單,就是修改cmap的值為'gray'。示例代碼如下:
import cv2 import matplotlib.pyplot as plt #讀入彩色圖片 messi=cv2.imread('messi.jpg',0) #使用opencv的imshow顯示圖片 cv2.imshow('messi_cv',messi) cv2.waitKey(0) cv2.destroyAllWindows() #使用matplotlib.pyplot的imshow顯示圖片 #cmap使用默認(rèn)值 plt.imshow(messi),plt.title('messi_camp_default') plt.xticks([]),plt.yticks([]) #隱藏坐標(biāo)軸 plt.show() #使用matplotlib.pyplot的imshow顯示圖片 #cmap設(shè)置為'gray' plt.imshow(messi,cmap='gray'),plt.title('messi_camp_gray') plt.xticks([]),plt.yticks([]) #隱藏坐標(biāo)軸 plt.show()
運(yùn)行結(jié)果為:
左邊是cv2.imshow的顯示結(jié)果,中間和右邊的是plt.imshow的顯示結(jié)果。
另外,cmap的值除了可以取默認(rèn)參數(shù)及'gray'外,還有很多值可供我們選擇,詳細(xì)的說明在這里。其實(shí)這些東西了解下就行,等實(shí)際使用時(shí),查閱下、試一試。根據(jù)需要選擇合適的就可以了。
注:
1.關(guān)于matplotlib里的imshow函數(shù)更詳細(xì)的說明在這里。
2.關(guān)于matplotlib.matplotlibrc文檔更詳細(xì)的說明在這里。
3.如果想查看或編輯自己電腦里的matplotlibrc文件,可使用此命令matplotlib.matplotlib_fname()獲取路徑。
三、總結(jié)
由于OpenCV里的imshow和Matplotlib里的imshow的一些差異,在使用時(shí)主要是要注意兩點(diǎn):
1.顯示彩色圖時(shí),要把b、r通道調(diào)換一下。
2.顯示灰度圖時(shí),記得設(shè)置cmap的值為'gray'。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
numpy.bincount用于復(fù)數(shù)權(quán)重的方法
numpy.bincount是NumPy庫中的一個(gè)函數(shù),它用于計(jì)算整數(shù)數(shù)組中每個(gè)值的出現(xiàn)次數(shù),numpy.bincount函數(shù)在統(tǒng)計(jì)整數(shù)數(shù)組中每個(gè)值的出現(xiàn)次數(shù)或權(quán)重和時(shí)非常有用,本文給大家介紹numpy.bincount如何用于復(fù)數(shù)權(quán)重,感興趣的朋友跟隨小編一起看看吧2023-11-11構(gòu)建Python中的分布式系統(tǒng)結(jié)合Celery與RabbitMQ
在本文中,我們深入探討了如何利用Celery和RabbitMQ構(gòu)建Python中的分布式系統(tǒng),我們首先介紹了Celery和RabbitMQ的概念及其優(yōu)勢(shì),然后展示了如何結(jié)合它們來創(chuàng)建一個(gè)簡單但功能強(qiáng)大的分布式系統(tǒng),感興趣的朋友跟隨小編一起看看吧2024-05-05python獲取外網(wǎng)IP并發(fā)郵件的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猵ython獲取外網(wǎng)IP并發(fā)郵件的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10python中for循環(huán)的多種使用實(shí)例
for語句是Python中執(zhí)行迭代的兩個(gè)語句之一,另一個(gè)語句是while,下面這篇文章主要給大家介紹了關(guān)于python中for循環(huán)的多種使用方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09