1. 程式人生 > >讀取cv.VideoCapture(0)的frame幀轉變為PIL.Image圖片格式時遇到的坑

讀取cv.VideoCapture(0)的frame幀轉變為PIL.Image圖片格式時遇到的坑

在專案中遇到一個問題是想將VideoCapture()讀到的frame圖片轉變成PIL的Image圖片格式。

坑1:BGR還是RGB模式?

興沖沖地在在網上找到一段程式碼,將opencv中的imread()影象轉成PIL.Image格式,詳見python中PIL.Image和OpenCV影象格式相互轉換

OpenCV轉換成PIL.Image格式:

import cv2  
from PIL import Image  
import numpy  

img = cv2.imread("plane.jpg")  
cv2.imshow("OpenCV",img)  
image = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))  
image.show()  
cv2.waitKey()  

於是將image = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))複製了一遍,結果得到

open cv error: (-215) scn == 3 || scn == 4 in function cvtColor

的錯誤,參考了下stackflow上類似的回答發覺應該是顏色空間的問題——意思是原來的顏色空間和要改的顏色空間是一樣的,比如原來是灰度空間,就不用再cv.COLOR_BGR2GRAY了,於是這才意識到有可能VideoCapture(0)imread()得到的顏色空間是不同的。

其實VideoCapture()與imread()得到影象的顏色空間並不相同,VideoCapture

得到的圖片是RGB空間的,而imread得到的圖片是BGR空間的,因此這裡不需要cv2.cvtColor(imgmcv2.COLOR_BGR2RGB),直接image = Image.fromarray(frame)即可,frameVideoCapture讀到的幀,Image.fromarray()可以將np.array轉成image格式的影象。

坑2 : type(frame)的結果是 ‘Nonetype’

上一步改完後image = Image.fromarray(frame)後還是會報錯,我尋思是不是frame的格式還是有問題,結果測試得到opencv讀取的幀是Nonetype攝像頭也沒有畫面。

報的錯是Image.fromarray(object)沒有Nonetype這種格式,仔細想了想,以前久遇到過這種問題,就是opencv的VideoCapture沒有讀到幀的時候frame就會返回Nonetype,而ret返回的是False,所以在讀取視訊的迴圈中加一個條件判斷語句即可,if ret ==True:的時候進行操作:

cap = cv2.VideoCapture(0)
while(1):
    ret,frame =cap.read()
    if ret==True:
        print (type(frame))
        print (ret)#觀察frame和ret的型別

        img = Image.fromarray(frame)#完成np.array向PIL.Image格式的轉換

        cv2.imshow("frame", frame)#正常顯示frame
        cv2.waitKey(1)

後面得到的結果就是retTrue,frame的type()為np.array

總結

其實出現這麼多的坑就是因為對opencv讀取圖片的顏色空間和資料格式不清楚,他們裡面有BGRRGB顏色空間,而一般cv2.imread()讀取的圖片都是BGR顏色空間的圖片,cv2.VideoCapture()獲取的視訊幀是RGB顏色空間的圖片。PIL(Python Image Library)讀取的圖片是RGB顏色空間的。
opencv讀取的圖片不管是視訊幀還是圖片都是矩陣形式,即np.array,轉PIL.Image格式用PIL.Image.fromarray()函式即可。