读取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()函数即可。

你可能感兴趣的:(python,opencv)