讀取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)
即可,frame
是VideoCapture
讀到的幀,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)
後面得到的結果就是ret
為True
,frame
的type()為np.array
。
總結
其實出現這麼多的坑就是因為對opencv讀取圖片的顏色空間和資料格式不清楚,他們裡面有BGR
和RGB
顏色空間,而一般cv2.imread()
讀取的圖片都是BGR顏色空間的圖片,cv2.VideoCapture()
獲取的視訊幀是RGB
顏色空間的圖片。PIL(Python Image Library
)讀取的圖片是RGB
顏色空間的。
opencv讀取的圖片不管是視訊幀還是圖片都是矩陣形式,即np.array
,轉PIL.Image
格式用PIL.Image.fromarray()
函式即可。