前几次使用Python+Opencv,对网络摄像头,USB摄像头进行数据采集,基本流程已经跑通,没什么大问题。最近项目中使用了一款120fps/s的USB摄像头,但是调试好代码运行后,问题来了。
遇到的问题
120fps,每次只能读取30多张图片或者最多也在40张以下。根本达不到要求。
开始使用的代码
# -*- coding: cp936 -*-
"""
Author:NoamaNelson
Date:2019-11-19
Discription:Read Camaro picture and save
"""
import cv2,os,time
import numpy as np
class CamaroCap(object):
""" 打开视频流 """
def __init__(self):
self.cap = cv2.VideoCapture(0)
""" 图片信息打印 """
def get_image_info(self,image):
print(type(image))
print(image.shape)
print(image.size)
print(image.dtype)
pixel_data = np.array(image)
print(pixel_data)
""" 逐帧读取数据并保存图片到本地制定位置 """
def Camaro_image(self):
i = 0
while(True):
ret,frame = self.cap.read() #ret:True或者False,代表有没有读取到图片;frame:表示截取到一帧的图片
if ret == False:
break
self.get_image_info(frame) # print("打印图片信息") 注意:调试的时候可以打开,如果是一直运行程序,建议把这行代码注释掉,避免影响内存占用
cv2.imshow('capture',frame) # 展示图片
cv2.imwrite(r"D:\image\\"+ str(i) + ".jpg",frame) # 保存图片
i = i + 1
if cv2.waitKey(1) & 0xFF == ord('q'): #
break
if __name__ == '__main__':
outmasages = CamaroCap()
outmasages.Camaro_image() # 调用摄像头
outmasages.cap.release() # 释放对象和销毁窗口
cv2.destroyAllWindows()
问题分析
- 笔者发现,每次在摄像头的控制软件上调参数,比如分辨率设置800600,但是运行代码后依然是640480,why?why?
- 该摄像头在640*480分辨率下,支持120fps,笔者在代码中限制了下帧率为60fps,但还是每秒只能获取30多张图片,这又是Why?why?
self.cap.set(cv2.CAP_PROP_FPS, 60)
- 开始求助网络,从网上搜了很多,终于是看到了希望
- 原来以上问题在于,博主链接
分析结论
笔者使用的USB相机,同样支持视频编码格式为YUY2/MJPG,但是Opencv默认读取的是YUY2,而笔者在摄像头控制软件上查看了下,YUY2格式的各种分辨率下的帧率最大才40帧,那么这就对了,就知道为啥一直是30-40张图片了。那么就需要在脚本中修改格式为MJPG,从以上博主的链接中可以看到:
参数 | 值 | 功能/意义 |
---|---|---|
CV_CAP_PROP_POS_MSEC | 0 | 视频文件的当前位置(以毫秒为单位)或视频捕获时间戳 |
CV_CAP_PROP_POS_FRAMES | 1 | 基于0的索引将被解码/捕获下一帧 |
CV_CAP_PROP_POS_AVI_RATIO | 2 | 视频文件相对位置:0 - 电影的开始,电影的1 - 结束 |
CV_CAP_PROP_FRAME_WIDTH | 3 | 视频里每一帧的宽 |
CV_CAP_PROP_FRAME_HEIGHT | 4 | 视频里每一帧的高 |
CV_CAP_PROP_FPS | 5 | 视频的帧速 |
CV_CAP_PROP_FOURCC | 6 | 4个字符表示的视频编码器格式 |
CV_CAP_PROP_FRAME_COUNT | 7 | 视频的帧数 |
CV_CAP_PROP_FORMAT | 8 | byretrieve()返回的Mat对象的格式 |
CV_CAP_PROP_MODE | 9 | 指示当前捕获模式的后端特定值 |
CV_CAP_PROP_BRIGHTNESS | 10 | 图像的亮度(仅适用于相机) |
CV_CAP_PROP_CONTRAST | 11 | 图像对比度(仅适用于相机) |
CV_CAP_PROP_SATURATION | 12 | 图像的饱和度(仅适用于相机) |
CV_CAP_PROP_HUE | 13 | 图像的色相(仅适用于相机) |
CV_CAP_PROP_GAIN | 14 | 图像的增益(仅适用于相机) |
CV_CAP_PROP_EXPOSURE | 15 | 曝光(仅适用于相机) |
CV_CAP_PROP_CONVERT_RGB | 16 | 表示图像是否应转换为RGB的布尔标志 |
CV_CAP_PROP_WHITE_BALANCE | 17 | 目前不支持 |
CV_CAP_PROP_RECTIFICATION | 18 | 立体摄像机的整流标志(注意:只有当前支持DC1394 v 2.x后端) |
- 如果要修改分辨率就必须使用:
CAP_PROP_FRAME_WIDTH 和 CAP_PROP_FRAME_HEIGHT进行设置宽和高
- 要修改格式为MJPG编码必须使用:
CV_CAP_PROP_FOURCC
- 那么就需要在代码中加入:
#self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
#self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 600)
#self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
修改后的代码
# -*- coding: cp936 -*-
"""
Author:zhangbo
Date:2019-11-07
Discription:Read Camaro picture and save
"""
import cv2,os,time,datetime
import numpy as np
class CamaroCap(object):
""" 打开视频流 """
def __init__(self):
self.cap = cv2.VideoCapture(0)
#self.cap.set(cv2.CAP_PROP_FPS, 120) 这个有时候生效,有时候不生效不知道是什么原因
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 600)
self.cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
""" 图片信息打印 """
def get_image_info(self,image):
print(type(image))
print(image.shape)
print(image.size)
print(image.dtype)
pixel_data = np.array(image)
print(pixel_data)
""" 逐帧读取数据并保存图片到本地制定位置 """
def Camaro_image(self):
i = 0
while(True):
ret,frame = self.cap.read() #ret:True或者False,代表有没有读取到图片;frame:表示截取到一帧的图片
if ret == False:
break
#self.get_image_info(frame) # print("打印图片信息") 注意:调试的时候可以打开,如果是一直运行程序,建议把这行代码注释掉,避免影响内存占用
cv2.imshow('capture',frame) # 展示图片
mtime = datetime.datetime.now().strftime('%Y-%m-%d_%H_%M_%S')
print(mtime)
cv2.imwrite(r"D:\image\\" + str(i) + str("-") + mtime + ".jpg",frame) # 保存图片
i = i + 1
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if __name__ == '__main__':
outmasages = CamaroCap()
outmasages.Camaro_image() # 调用摄像头
outmasages.cap.release() # 释放对象和销毁窗口
cv2.destroyAllWindows()