原文鏈接:http://www.juzicode.com/archives/5395
這篇文件介紹怎么用OpenCV-Python從靜態圖片文件中獲取圖像、顯示圖像,以及怎么保存靜態圖像文件。在OpenCV-Python教程:從視頻文件或相機獲取圖像、寫視頻文件 一文中介紹怎么讀取和保存視頻文件。
1、讀取圖片imread()
imread()方法在第1個位置參數傳入圖像文件的路徑,如果讀取文件成功返回一個numpy數組,如果獲取失敗將返回None。
這里需要注意的是獲取圖像失敗並不會拋異常,而是得到一個None,后面的imshow(),imwrite()等方法如果直接使用反而會導致異常。
下面的3個imread()的例子分別是錯誤的路徑、非圖片文件、正確路徑的圖片文件:
import cv2
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\lena2.jpg') #錯誤路徑
print('img:',img)
print('type(img):',type(img))
img = cv2.imread('..\\1.txt') #非圖片文件
print('img:',img)
print('type(img):',type(img))
img = cv2.imread('..\\lena.jpg') #圖片文件,正確路徑
print('img:',img)
print('type(img):',type(img))
運行結果:
cv2.__version__: 4.5.2
img: None
type(img): <class 'NoneType'> #錯誤路徑
img: None
type(img): <class 'NoneType'> #非圖片文件
img: [[[128 138 225]
[127 137 224]
[126 136 224]
...
...
[ 81 68 176]
[ 81 72 183]
[ 84 74 188]]]
type(img): <class 'numpy.ndarray'> #圖片文件,正確路徑
另外讀取圖像還可以在第2個位置參數寫入如下3種模式:
cv2.IMREAD_COLOR | 缺省方式,讀取圖像為BGR 8-bit 格式. |
cv2.IMREAD_UNCHANGED | 圖像格式不做任何改變,可用在讀取帶alpha通道的圖片 |
cv2.IMREAD_GRAYSCALE | 讀取圖像為轉換為灰度圖 |
下面這個例子從3張圖片中按照IMREAD_UNCHANGED模式讀取,通過返回numpy數組的shape屬性可以看到不同的3張圖片的通道數的差異:
import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\lena.jpg',cv2.IMREAD_UNCHANGED)
print('img.shape:',img.shape)
img2 = cv2.imread('..\\opencv-logo.png',cv2.IMREAD_UNCHANGED )
print('img2.shape:',img2.shape)
img3 = cv2.imread('..\\left05.jpg',cv2.IMREAD_UNCHANGED )
print('img3.shape:',img3.shape)
運行結果:
VX公眾號: 桔子code / juzicode.com
cv2.__version__: 3.4.1
img.shape: (512, 512, 3) #3通道圖像
img2.shape: (739, 600, 4) #4通道圖像
img3.shape: (480, 640) #灰度圖
需要注意的是圖像的寬度是width=cols=img.shape[1],高度height=rows=img.shape[0]。
2、顯示圖像imshow()
imshow()可以用來顯示圖片,第1個參數為顯示窗口名稱,第2個參數是imread()等方法生成的圖像實例。
為了觀察顯示效果,一般需要配合waitKey()使用,waitKey()傳入的參數如果為0,會無限等待直到任何按鍵按下,或者傳入其他數值參數表示等待時長,單位為ms,時長結束后顯示圖像窗口會關閉。
下面這個例子中增加了讀出圖像的判斷,如果獲取圖像為None則退出,如果獲取圖像成功才顯示。
這個例子中waitKey()入參使用了0和5000,第1次的0表示無限等待,直到按鍵按下,第2次表示等待5000ms后顯示窗口自動關閉。
import sys
import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\lena.jpg')
#print('img:',img)
print('type(img):',type(img))
if img is None:
print('讀出的圖像為空')
sys.exit(-1)
cv2.imshow('lena',img)
cv2.waitKey(0)
cv2.imshow('lena2',img)
cv2.waitKey(5000)
運行結果:
VX公眾號: 桔子code / juzicode.com
cv2.__version__: 4.5.2
type(img): <class 'numpy.ndarray'>
除了前面用imshow()顯示圖像,還可以通過resizeWindow()等函數調整窗口大小再顯示圖像,如果顯示的圖像太多,還可以使用destroyWindow()銷毀顯示窗口。
2.1、調整窗口nameWindow()、resizeWindow()
使用imshow()方法顯示圖像時,默認是以圖像的像素大小顯示的,可以通過nameWindow(窗口名稱,cv2.WINDOW_NORMAL)命名窗口,再使用resizeWindow(窗口名稱,窗口寬度,窗口高度)縮放窗口,最后使用imshow()顯示圖像,注意三者都在同一個窗口名稱上操作。
import sys
import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\lena.jpg')
#print('img:',img)
print('type(img):',type(img))
if img is None:
print('讀出的圖像為空')
sys.exit(-1)
#原圖大小顯示
cv2.imshow('lena',img)
#縮小顯示
rows,cols = img.shape[0],img.shape[1]
cv2.namedWindow('lena-down', cv2.WINDOW_NORMAL )#cv2.WINDOW_AUTOSIZE)
cv2.resizeWindow('lena-down',(int(cols*0.5),int(rows*0.5)))
cv2.imshow('lena-down',img)
#放大顯示
cv2.namedWindow('lena-up', cv2.WINDOW_NORMAL )
cv2.resizeWindow('lena-up',(int(cols*1.3),int(rows*1.3)))
cv2.imshow('lena-up',img)
cv2.waitKey(0)
運行結果:
2.2、銷毀窗口destroyWindow()、destroyAllWindows()
在調試過程中如果顯示的窗口過多時,可以使用destroyWindow(窗口名稱)單獨關閉某個顯示窗口,也可以使用destroyAllWindows()關閉所有顯示窗口。
下面這個例子中先用destroyWindow()關閉名稱為lena-up的窗口,再用destroyAllWindows()關閉其他的所有窗口:
import sys
import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\lena.jpg')
#print('img:',img)
print('type(img):',type(img))
if img is None:
print('讀出的圖像為空')
sys.exit(-1)
#原圖大小顯示
cv2.imshow('lena',img)
#縮小顯示
rows,cols = img.shape[0],img.shape[1]
cv2.namedWindow('lena-down', cv2.WINDOW_NORMAL )#cv2.WINDOW_AUTOSIZE)
cv2.resizeWindow('lena-down',(int(cols*0.5),int(rows*0.5)))
cv2.imshow('lena-down',img)
#放大顯示
cv2.namedWindow('lena-up', cv2.WINDOW_NORMAL )
cv2.resizeWindow('lena-up',(int(cols*1.3),int(rows*1.3)))
cv2.imshow('lena-up',img)
cv2.waitKey(0)
cv2.destroyWindow('lena-up') #關閉lena-up窗口
cv2.waitKey(0)
cv2.destroyAllWindows() #關閉所有顯示窗口
2.3、顯示封裝例程
這個例程將顯示圖像的多個操作步驟封裝在一個函數中:
dbg_is_show = False
def show_img(win_name,img,wait_time=0,img_ratio=0.15,is_show=True):
if is_show is not True:
return
rows = img.shape[0]
cols = img.shape[1]
cv2.namedWindow(win_name, cv2.WINDOW_NORMAL )#cv2.WINDOW_AUTOSIZE)
cv2.resizeWindow(win_name,(int(cols*img_ratio),int(rows*img_ratio)))
cv2.imshow(win_name,img)
cv2.waitKey(wait_time)
3、寫入圖片imwrite()
imwrite()第1個位置參數是寫入的文件名稱,文件名稱的后綴決定了圖片文件的格式,第2個參數為圖像實例。
下面這個例子中將圖像分別保存在bmp,jpg格式:
import sys
import cv2
print('VX公眾號: 桔子code / juzicode.com')
print('cv2.__version__:',cv2.__version__)
img = cv2.imread('..\\lena.jpg')
#print('img:',img)
print('type(img):',type(img))
if img is None:
print('讀出的圖像為空')
sys.exit(-1)
cv2.imwrite('lena.bmp',img)
cv2.imwrite('lena.png',img)
cv2.imwrite('lena.txt',img)
這個例子中倒數第3行和倒數第2行將imread()讀出的圖像實例分別寫入為bmp和jpg格式的文件,在當前工作路徑下就會看到生成了2個新的文件。最后一行故意寫入一個txt文件,該格式並不是圖像文件的格式,會拋出異常:
error: (-2:Unspecified error) could not find a writer for the specified extension in function 'cv::imwrite_'
小結:這篇文章介紹了怎么從圖片文件獲取圖像、顯示圖像、寫入圖像的操作方法。顯示圖像的方法就好像Python的print()函數,可以將圖像處理過程的中間過程顯示出來,觀察變換的效果達到調試目的。