對于 matlab 起家做數字圖像處理的人來講都非常适應matlab對圖像處理的操作和思路,尤其是它可以非常友善直覺的看到圖像的RGB值。
由于最近在研究深度學習的計算機視覺方面的東西,于是完全自學接觸到opencv的Python接口,後面需要用到opencv幫助做一些圖像處理。但是作為一個自學小白,第一步就被讀取資料卡住了一晚上,後來終于想明白了。我查了半天,也沒有人對這個顯示做過多的說明,可能這個問題太簡單了不需要多說,但是畢竟我可能比較笨,是以就由我多嘴來說說這個事。
讀取圖像代碼:
import numpy as np
import cv2
im=cv2.imread("123.png")
print (im)
'''for x in range(10):print (im[1,x])'''
随便截了一張RGB圖,讀進來,發現是一堆這個。
請原諒我的無知,一開始我确實看不明白這個東西,想了很久,于是打開了matlab也讀了進來,後來想明白了。如果大家還是不明白可以自己讀入matlab和python做一個對比。
opencv的Python接口對于RGB圖像的讀入以後化成了标準的numpy數組的形式,但是是多元數組。顯示上,他是一個像素一個像素來顯示的,一顯示就是三個次元也就是【211 101 5】【裡面三個值是對應一個像素的】。然後一行一行的顯示,由于太多了,中間用...來省略了;每一行顯示完了,顯示第二行直到最後一行。同時opencv讀入的RGB圖像顯示通道是BGR,也就是第一個211的值其實是B,這一點和MATLAB是不同的,千萬注意。
也就是說這個奇葩的顯示說的其實是:
第一行第一個像素BGR值為:【211 101 5】 第一行第二個像素BGR值為:【210 100 4】中間太多了省略掉...,即按照以上的形式來顯示,第一行倒數第二個是【194 74 8】,第一行最後一個是【194 74 8】,然後第一行顯示完了,開始顯示第二行。
就這樣有省略之後,一直到最後。以上是我做的實驗。
下面貼一個整體上詳細的介紹:
python的便捷是如此的引人着迷,而opencv給python提供的接口使我們能夠使用python來快速驗證我們的想法,或者與别的子產品快速結合,在這個系列文章我會通過jupyter notebook來快速展示opencv的使用
#在開頭引入必要的庫
import matplotlib.pyplot as plt
import numpy as np
import cv2
#ipython
%matplotlib inline
圖像讀取
opencv使用imread讀取圖檔,imshow顯示圖檔,但是對于我而言,常使用jupyter作為展示的工具,imshow在浏覽器環境中就失去了它的作用,是以我會使用matplotlib來展示
#讀取一張圖檔
cv2.imread(img,flag)
#img這一參數中填入圖檔的完全路徑或者相對路徑
這裡我們需要稍微了解下flag這個參數,這決定了opencv是如何讀入我們的圖像的
我們知道通常圖像每個像素點的顔色我們以RGB的格式來描述(或者RGBA),可以通過三基色(red,green,blue)來描述所有顔色,對于透明圖檔我們會增加一個a(alpha)來描述其顔色的透明度.
cv2.IMREAD_COLOR : 讀入圖檔,任何與透明度相關通道的會被忽視,預設以這種方式讀入.
cv2.IMREAD_GRAYSCALE : 以灰階圖的形式讀入圖檔.
cv2.IMREAD_UNCHANGED : 保留讀取圖檔原有的顔色通道.
可以簡單的用-1,0,1來分别表示這3個flag
就讓我們從著名的lenna圖開始吧
lenna_img = cv2.imread("lena.jpg")
plt.imshow(lenna_img)
plt.axis("off")#去除坐标軸
plt.show()
當把這張圖檔列印出來後,你一定在疑惑,咦,這張圖怎麼變青色了?
原因就在于opencv預設的imread是以BGR的方式進行存儲的,而matplotlib的imshow預設則是以RGB格式展示,是以此處我們必須對圖檔的通道進行轉換
lenna_img = cv2.cvtColor(lenna_img,cv2.COLOR_BGR2RGB)
plt.imshow(lenna_img)
plt.axis("off")
plt.show()
Lenna終于恢複了她的本來樣子了
這裡我們了解一下cvtColor這個函數,它的第一個參數是圖檔,第二個參數則是顔色通道的轉化方式
它的命名是有規律的通常以COLOR作為開頭,後面則跟着它的轉化方式,BGR通道轉化為RGB,是以就是cv2.COLOR_BGR2RGB
你可以試着猜測從RGB通道轉化為BGR通道的api名,通過補全驗證你的想法
我們在剛剛使用了預設的flag讀入了圖檔,那麼讓我們用用另外兩個試試效果
gray_lenna_img = cv2.imread("lena.jpg",0)
orign_lenna_img = cv2.imread("lena.jpg",1)
plt.subplot(121)
plt.imshow(gray_lenna_img,cmap=plt.cm.gray)
plt.axis("off")
plt.subplot(122)
orign_lenna_img = cv2.cvtColor(orign_lenna_img,cv2.COLOR_BGR2RGB)
plt.imshow(orign_lenna_img)
plt.axis("off")
plt.show()
因為lenna圖并沒有包含透明度這一通道,讀入的仍然是BGR格式,是以我們從lenna圖是看不出差別的
圖檔在python下的儲存方式
opencv的一個Image對象在python和C++下的存儲方式是不同的,在c++下,通過opencv實作的Mat來進行存儲,而python下則基于numpy
numpy對于使用python進行科學計算的人都不算陌生,它為python提供了一個高效的矩陣運算子產品.
這就意味着我們可以直接使用numpy的api對圖檔進行計算和處理.
print("Lenna圖在python中存儲的類型為",type(lenna_img))
print("讀入lenna圖的shape為",lenna_img.shape)
print("以灰白圖讀入lenna圖的shape為",gray_lenna_img.shape)
#Lenna圖在python中存儲的類型為
#讀入lenna圖的shape為 (512, 512, 3)
#以灰白圖讀入lenna圖的shape為 (512, 512)
上文實作的bgr裝RGB我們也可以使用numpy來輕松的實作
lenna_img = cv2.imread("lena.jpg")
b,g,r = cv2.split(lenna_img)
lenna_img = cv2.merge([r,g,b])
plt.imshow(lenna_img)
plt.axis("off")
plt.show()
#結果如下
我們可以對之前的函數進行一些包裝,畢竟每次都要設定坐标軸為off怎麼也會厭煩的啊
def show_cv_img(cv_image):
image = cv2.cvtColor(cv_image,cv2.COLOR_BGR2RGB)
plt.imshow(image)
plt.axis("off")
考慮到subplot此處沒有直接plt.show
show_cv_img(cv2.imread("lena.jpg"))#jupyter result
圖檔的展示與存儲
雖然說我們通常使用jupyter來使用opencv,但還是要了解下opencv預設的imshow
img = cv2.imread("lenna.jpg")
cv2.namedWindow('image', cv2.WINDOW_NORMAL)#給顯示的視窗命名,後面的flag預設為cv2.WINDOW_AUTOSIZE,自動調整邊框
#,但是在條形圖過長時,使用windownormal我們可以自行調整邊框
cv2.imshow('image',img)#展示圖檔
cv2.waitKey(0)#等待按鍵按下
cv2.destroyAllWindows()#清除所有視窗
我們可以使用imwrite來存儲一張圖檔,接受一個numpy的數組作為參數.
cv2.imwrite('cope_lenna_img.jpg',lenna_img)
#result: True
他會傳回一個bool值來表示它是否成功存儲.
我們成功在目前目錄存儲了一個叫做copy_lenna_img.jpg的圖像.
Warning:
注意字尾.你的字尾是jpg還是png決定它以怎樣的方式儲存
Opencv對于圖像的讀入和存儲都已經封裝好了給我們,是我們能夠輕松的讀入,存儲,避免去了解圖檔檔案的格式才能讀取,存儲圖檔,但僅僅這樣顯然不是opencv的真正面目,還不如直接用pillow呢.
好了,以上系統的介紹是我貼的一個部落格上我覺得寫的特别好的大神的,連結在Referece中,其中的圖太麻煩,我就沒貼,想象一下就OK啦
Reference:https://www.cnblogs.com/lynsyklate/p/7720045.htmlwww.cnblogs.com