Python+Opencv读取高帧率USB摄像头问题

前几次使用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,从以上博主的链接中可以看到:

  • 如果要修改分辨率就必须使用:
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()
    
本文转载于网络 如有侵权请联系删除

相关文章

  • Java构造函数调用顺序问题

    参考链接:Java构造函数今天对Java的构造函数调用顺序进行研究,使用的是与C++类似的方法,即不对源码进行研究,而是直接通过打印代码对构造函数的调用顺序进行研究。 代码如下,使用的是Java核心技术中的代码,对其进行了改造,在构造函数中加入了输出信息 publicclassConstructorTest{  publicstaticvoidmain(String[]args)  {  Employeetemp=newEmployee();   }}classEmployee{  privatestaticintnextId;  privatestaticintcounter;  privateintid;  privateStringname="";//instancefieldinitialization  privatedoublesalary;  //staticinitializationblock  static  {   Randomgenerator=newRandom();   //setnextIdtoarandomnumberbetween0

  • Cocos2d-js中的简易MVC框架(一)框架简介

    一、框架简介今天我将把我写的一套适用于Cocos2d-JS的一套MVC框架分享给大家。首先我先简单介绍一下MVC,然后再逐步的介绍我写的mvc框架和在游戏中的具体应用。MVC借用百度百科的解释:MVC全名是ModelViewController,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。这里实现的MVC比较简单明了,关系图如下: 节点功能1.View:包括Scene和Layer,负责显示和接收用户反馈,将用户操作反馈通过消息发送给Mediator处理。2.Mediator:包括DirectorMediator、SceneMediator和LayerMediator,持有View对象,负责接收消息进行处理,更新UI和数据。DirectorMediator负责维护场景间的关系和切换;SceneMediat

  • C++ 插入排序,冒泡排序和选择排序

    大学的时候学过C,现在已经忘得七七八八了,现在想再学一下C/C++。刚试着重写/温习了3个最简单的排序算法。插入排序:依次将右边未排序的元素插入到左边已排序序列的合适位置。时间复杂度:O(n^2)float*sort_insertion(floata[],intlen_a) { /*插入排序类似我们排序扑克牌*/ for(inti=1;i<len_a;i++) { floatto_insert=a[i]; //索引0到i-1已排好序 intj; for(j=i-1;a[j]>to_insertandj>=0;j--) a[j+1]=a[j];//大的往后退一位 a[j+1]=to_insert;//a[j]>to_insert不成立时j+1的值即是待插入的位置 } returna; }复制冒泡排序和选择排序大学都学过,不再赘述。冒泡排序:时间复杂度:O(n^2)float*sort_bubble(floata[],intlen_a) { /*冒泡排序依次比较相邻的两个元素,如果顺序错误就将它们的位置交换*/ floattemp; for(inti=0;i<

  • SAP Fiori里的Adapt UI按钮,神出鬼没的奥秘

    今天是2020年2月2日鼠年大年初九,这是Jerry鼠年的第9篇文章,也是汪子熙公众号总共第208篇原创文章。这几天大家在家一日游的感觉如何?看巧手的网友用瓜子自制的霸王龙:工作中Jerry的同事曾经问过我一个问题,Fiori界面上这个AdaptUI的按钮,为什么有的系统上有,有的系统上没有?FioriKeyUser正是通过点击该按钮,进入FioriUI的Adaptation模式,从而实现在屏幕上新增扩展字段的目的。比较下面两个不同系统的截图:为什么这个AdaptUI按钮,如此神出鬼没,有的系统上有显示,有的没有?自己动手,丰衣足食。假设你的身边找不到Fiori专家,如何通过自己在系统里调试的方法找到问题的答案呢?Jerry之前的文章Jerry的Fiori原创文章合集,搜集了很多案例,讲述了如何通过单步调试,去分析和处理Fiori开发工作中的一些常见问题。现在我们再次通过单步调试的方式来分析这个AdaptUI按钮动态显示与否的逻辑。首先根据Jerry这篇博客介绍的SAPUI5控件在浏览器端的渲染逻辑的知识,找出是一个ID为sap.ushell.plugins.rta的插件,负责管理该A

  • android 中resources管理

    主要存在于res/value文件夹中定义: dimen.xml:主要用于设置像素默认值<resources> res/values/dimens.xml <dimenname="sp_12">12sp</dimen> <dimenname="sp_13">13sp</dimen>  <dimenname="dip_40">40dip</dimen>  <dimenname="dip_45">45dip</dimen> </resources>复制代码使用:intwidth=getContext().getResources().getDimension(R.dimen.tab_width);复制xml文件使用:android:layout_width="@dimen/tab_width"复制color.xml设置颜色<?xmlversion="1.0&q

  • hbase shell基础和常用命令详解(转)

    HBaseshell的基本用法 hbase提供了一个shell的终端给用户交互。使用命令hbaseshell进入命令界面。通过执行help可以看到命令的帮助信息。 以网上的一个学生成绩表的例子来演示hbase的用法。 name grad course math art Tom 5 97 87 Jim 4 89 80 这里grad对于表来说是一个只有它自己的列族,course对于表来说是一个有两个列的列族,这个列族由两个列组成math和art,当然我们可以根据我们的需要在course中建立更多的列族,如computer,physics等相应的列添加入course列族。 (1)建立一个表scores,有两个列族grad和courese 代码如下: hbase(main):001:0>create‘scores','grade',‘course'复制 可以使用list命令来查看当前HBase里有哪些表。使用describe命令来查看表结构。(记得所有的表明、列名都需要加上引号) (2)按设计的表结构插入值:  代码如下: p

  • dubbo启动报错failed to bind nettyserver on

    dubbo报错       今天启动项目的时候,关掉了custom服务, <dubbo:consumercheck="false"/>复制 并且关掉了spring的elastic-job, <!--<importresource="cloud-elastic-job.xml"/>-->复制 但是还是报错,看了下错误代码,原因是因为 devip的dubbo服务需要占用12500端口,但是我本地的12500端口被占用,映射到我本地的12500端口的时候报错了,kill掉就好了。   查找本地12500端口被哪个进程占用 lsof-itcp:12500复制  lsof-itcp:12500     ctgu_czy

  • vue-element-admin左侧目录的三级展示

    目的:总是忘记,实际上demo项目说的也很明白想要结果如下     解决办法:需要有一个空白跳转页即可 最外层的index.html //空白跳转页 <template> <div> <router-view/> </div> </template>复制 注意router里的二级目录(第二个children的)指向应该是 component:()=>import("@/views/productXXXXX/index"),复制    

  • 28、数组中出现次数超过一半的数字

    一、题目 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。 二、解法 1importjava.util.HashMap; 2publicclassSolution{ 3publicintMoreThanHalfNum_Solution(int[]array){ 4HashMap<Integer,Integer>hasharray=newHashMap(); 5for(inti=0;i<array.length;i++){ 6Integertemp=hasharray.get(array[i]);//从hashmap中获取值 7if(temp==null){//如果没有,则添加到hashmap中去 8hasharray.put(array[i],1); 9temp=1; 10}else{ 11hasharray.put(array[i],++temp); 12} 13if(temp>=array.len

  • [MIREX] MIREX评测介绍

    MIREX作为国际最权威音频检索评测大赛,竟然在百度上找不到任何介绍,只有几个与什么搜狗、腾讯获得什么成绩相关的检索内容,相比而言,TRECVID的内容收到重视多了...由于研究生阶段主要研究音频领域,需要对整个领域有一个大致的了解,感觉还是从MIREX入手比较合适,所以借此机会也与大家分享一记。 MIREX全称MusicInformationRetrievalEvaluationeXchange,即音乐信息检索评测,至于eXchange放在这不太清楚什么意思,或许与“交流”类似的含义吧,比赛由IMIRSEL承办,每个子项目由任务组织者设计并管理,这些任务组织者基本就是各个领域的领头专家。 【最普适的任务:音频分类任务】 AudioClassification(Train/Test)Tasks 包含了以下几个子任务:1.美国流行音乐、拉丁音乐、韩国流行音乐的流派分类,2.音乐情感分类、韩国流行音乐情感分类,3.古典音乐的作曲家鉴别。这个任务做了很多年,感觉准确率到达一个瓶颈,不同任务的准确率基本上就稳定在0.65~0.8之间。 【音频相似度和检索】 AudioMusicSimil

  • 初学数位DP

    所谓数位dp,字面意思就是在数位上进行dp,数位的含义:一个数有个位、十位、百位、千位、等等,数的每一位就是数位。 数位DP一般应用于: 求出给定区间[A,B]内,符合条件P[i]的数i的个数。 条件P[i]一般与数的大小无关,而与数的组成有关 其实质就是换一种暴力枚举的方式,使得新的枚举方式满足dp的性质,然后记忆化就可以了。   参考来自以下链接 https://blog.csdn.net/zhangxian___/article/details/75304335 https://blog.csdn.net/qq_41958841/article/details/81637498 https://blog.csdn.net/wust_zzwh/article/details/52100392     以HDU2089为前提讨论,题目大意为,多组数据,每次给定区间[n,m],求在n到m中没有"62"或"4"的数的个数。 试想:我们如果能有一个函数count(intx),可以返回[0,x]之间符合题意的数的个数。那么是不是直接输出count(m)-cou

  • 为BlueLake主题增加自定义icon图标

    一、前言 hexo的Bluelake主题是我一直在用的,简单大方,很喜欢。但最近有了添加自定义icon图标的需求,比如,添加“地址”、“扫一扫”、“优惠券”等icon,还是很有必要研究一下如何制作的。 然后我就去了主题作者chaooo的github上留言,咨询其方法,作者回复的很快,按照作者的回复,成功将自定义图标制作出来了,也分享给有需要的人。 二、阿里妈妈图标库 官网地址:www.iconfont.cn/ icon图标使用指南:https://github.com/chaooo/hexo-theme-BlueLake/issues/99,在这里我是参考的font-class引用。 1、新建项目 首先通过github或新浪微博账号登录阿里妈妈图标库;然后,点击图标管理->我的项目->新建项目,如下图所示: 2、选图标 新建好项目之后,选择菜单栏里面的图标库,将喜欢的图标添加到购物车。如下图所示: 然后点击右上角的购物车标志,将图标添加到刚才新建的项目中。 3、下载项目 返回到我的项目,点击“下载至本地”按钮,进行下载。如下图所示: 下载文件的目录结构如下图所示

  • Exp2-后门原理与实践

    基础问题回答 1、例举你能想到的一个后门进入到你系统中的可能方式? 在非正规网站下载盗版软件,后门隐藏在盗版软件中。 受到诱骗点击某些可执行文件(表面上是压缩包,实际上是双击自动解压执行) 2、例举你知道的后门如何启动起来(win及linux)的方式? 替换或感染系统文件 后台插入免杀进程 3、Meterpreter有哪些给你印象深刻的功能? 可以干很多事情:获取密码,下载注册表,获取系统信息等 当目标机器重启之后仍然可以控制 可实现同时多个session操作 4、如何发现自己有系统有没有被安装后门? 定期使用强力的杀毒软件进行全盘查杀 查看自己主机上是否存在可疑进程 进行流量监控,查看是否有非法流量发出 实验内容 一、使用netcat获取主机操作Shell,cron启动 分别查看主机和kali的IP: 主机 kali Win10主机使用ncat程序监听本机的5205端口 kali虚拟机nc连接Win10主机反弹shell,成功getshell 通过cron命令启动 先用crontab-e指令编辑一条定时任务(crontab指令

  • Interview 位运算

    题意:两个数组,求一个区间使得或运算结果最大。 解法:因为位运算是无法越算越小的。所以只需要从头或到尾即可。   #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<stdlib.h> #include<queue> usingnamespacestd; intmain() { intn; while(~scanf("%d",&n)) { intsum=0,sum1=0,a,b; for(inti=0;i<n;i++) { scanf("%d",&a); sum|=a; } for(inti=0;i<n;i++) { scanf("%d",&b); sum1|=b; } printf("%d\n",sum+sum1); } return0; }复制  

  • Ubuntu/Linux使用命令行打开和关闭应用程序/ps命令和kill命令详解

      打开应用程序很容易,比如要打开firefox浏览器,我们可以在终端中输入命令: firefox& 最后加‘&’的目的是让应用firefox在后台运行,这样终端就不会被Firefox独占。 如果忘了写‘&’可以Ctrl+z,然后打bg回车 文件名中含空格要写成 '\' 关闭应用 ps是显示当前状态处于running的进程,grep表示在这些里搜索,而psaux是显示所有进程和其状态。 $psaux|grepevince   查到evince的进程 |:管道符号,command1|command2,将command1输出结果通过管道作为command2命令的输入参数. ***:~/Downloads$psaux|grepevince hellowo+ 6705 5.1 1.31202288107160pts/0 Sl  20:15  0:02evincetest.pdf hellowo+ 671

  • 样本分析(运营)工程师--面试准备

    这是面试前的准备,去网上收集了一些逆向、病毒样本分析的问题。 1.知道什么是函数调用约定吗? 2.讲一讲ctf中遇到的比较有趣的逆向题目? 3.有没有手动脱壳的经历? 4.PE文件结构熟悉吗? 5.给你一个病毒的样本如何对它进行分析呢? 6.看你学过应用密码学,讲一下一些密码算法?这里准备一个非对称加密(RSA),一个对称加密(DES)。 7.对断点的了解,软件、硬件、内存? 8.加壳的流程? 9.讲一下DLL注入,什么是DLL劫持? 10.了解哪些Windows安全机制? 11.hook学过吗? 12.简单描述一下取证? 13.如何修改DLL文件,使其加载时是固定基址? 14.漏洞挖掘讲一下。 15.内网横向渗透? 16.讲一下memcpy栈溢出? 17.对一个加壳的程序如何进行分析与破解?   本次想的问题就这么多,会问多少个再说吧。。。 1.知道什么是函数调用约定吗? 简单来说就是约定了参数传递的方式,和堆栈平衡由谁完成。如果一个函数被A调用,则函数可以收到A传递的参数(栈传递);且函数的返回值要给到A那里,在函数调用的过程由调用者清除栈,实现调用函数前后的栈平衡。参数

  • 迭代器模式(Iterator)

    迭代器模式(Iterator) 1.模式动机 在现实生活以及程序设计中,经常要访问一个聚合对象中的各个元素,如“数据结构”中的链表遍历,通常的做法是将链表的创建和遍历都放在同一个类中,但这种方式不利于程序的扩展,如果要更换遍历方法就必须修改程序源代码,这违背了“开闭原则”。 既然将遍历方法封装在聚合类中不可取,那么聚合类中不提供遍历方法,将遍历方法由用户自己实现是否可行呢?答案是同样不可取,因为这种方式会存在两个缺点: 暴露了聚合类的内部表示,使其数据不安全; 增加了客户的负担。 “迭代器模式”能较好地克服以上缺点,它在客户访问类与聚合类之间插入一个迭代器,这分离了聚合对象与其遍历行为,对客户也隐藏了其内部细节,且满足“单一职责原则”和“开闭原则”,如Java中的Collection、List、Set、Map等都包含了迭代器。 2.模式定义 迭代器(Iterator)模式的定义:提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。迭代器模式是一种对象行为型模式 3.模式结构 迭代器模式主要包含以下角色。 抽象聚合(Aggregate)角色:定义存储、添加、

  • sql表连接的几种方式

    这里有两张表TableA和TableB,分别是姓名表和年龄表,用于我们例子的测试数据 TableA id name 1 t1 2 t2 4 t4 TableB id age 1 18 2 20 3 19 在开发中我们的业务需求有时候是复杂的,多张表联合查询的时候是有多种方式的,面对不同的需求, 灵活使用不同的表连接方式,那么表连接分成哪几种呢?   表连接有几种? sql表连接分成外连接、内连接和交叉连接。   一.外连接 概述: 外连接包括三种,分别是左外连接、右外连接、全外连接。 对应的sql关键字:LEFT/RIGHT/FULLOUTERJOIN,通常我们都省略OUTER关键字,写成LEFT/RIGHT/FULLJOIN。 在左、右外连接中都会以一种表为基表,基表的所有行、列都会显示,外表如果和条件不匹配则所有的外表列值都为NULL。 全外连接则所有表的行、列都会显示,条件不匹配的值皆为NULL。     1.左外连接示例

  • 第二阶段冲刺6

    今日已做:碰撞后显示提示框,点击可以退出游戏,可以回到选关界面。 遇到问题:没能实现直接重新开始游戏。 明日任务:优化现有模块。

  • Docker仓库之分布式仓库 Harbor

    一、介绍 Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器,由vmware开源,其通过添加一些企业必需的功能特性, 例如安全、标识和管理等,扩展了开源DockerDistribution。作为一个企业级私有Registry服务器,Harbor提供了更好的性能和安全。 提升用户使用Registry构建和运行环境传输镜像的效率。Harbor支持安装在多个Registry节点的镜像资源复制, 镜像全部保存在私有Registry中,确保数据和知识产权在公司内部网络中管控,另外,Harbor也提供了高级的安全特性,诸如用户管理,访问控制和活动审计等 Harbor功能官方介绍 -基于角色的访问控制:用户与Docker镜像仓库通过“项目”进行组织管理,一个用户可以对多个镜像仓库在同一命名空间(project)里有不同的权限 -镜像复制:镜像可在多个Registry实例中复制(同步)。尤其适合于负载均衡,高可用,混合云和多云的场景 -图形化用户界面:用户可以通过浏览器来浏览,检索当前Docker镜像仓库,管理项目和命名空间 -AD/LDAP支:Harbor可以集成企业

  • 复合数据类型,英文词频统计

    作业要求:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2696 1.列表,元组,字典,集合分别如何增删改查及遍历。 列表的增删改查list1=list('thisisalist')#增加list1.append('!')#末尾增加元素list1.insert(2,'thisisindex3')#指定index增加一个元素#删除list1.pop(-1)#删除指定index的元素默认是-1return被删除元素的值dellist1[-1]if'!'inlist1:#删除第一个匹配的元素,如果不存在会报错,没有返回值list1.remove('!')#修改list1[0]='0'#元素赋值list1[0:2]=list('05')#分片赋值list1[1:1]=list('1234')#分片赋值插入新元素list1[1:5]=[]#分片赋值删除元素#查找if'a'inlist1:index=list1.index('a')#查找元素下标 字典的增删改查 #增加 dict1['key3']='value3'#字典可以自动添加

相关推荐

推荐阅读