• opencv学习之路(2)、读取视频,读取摄像头


      一、介绍

    视频读取本质上就是读取图像,因为视频是由一帧一帧图像组成的。1秒24帧基本就能流畅的读取视频了。 
    ①读取视频有两种方法: 
    A. VideoCapture cap; 
    cap.open(“1.avi”); 
    B. VideoCapture cap(“1.avi”);


    ②循环显示每一帧: 
    while(1) 

    Mat frame; //定义Mat变量,用来存储每一帧 
    cap>>frame; //读取当前帧方法一 
    //cap.read(frame); //读取当前帧方法二 
    imshow(“视频显示”, frame); //显示一帧画面 
    waitKey(30); //延时30ms 
    }

      二、读取视频示例程序

     1 #include<opencv2/opencv.hpp>
     2 using namespace cv;
     3 
     4 void main(){
     5     VideoCapture cap;
     6     cap.open("E://2.avi"); //打开视频,以上两句等价于VideoCapture cap("E://2.avi");
     7 
     8     //cap.open("http://www.laganiere.name/bike.avi");//也可以直接从网页中获取图片,前提是网页有视频,以及网速够快
     9     if(!cap.isOpened())//如果视频不能正常打开则返回
    10         return;
    11     Mat frame;
    12     while(1)
    13     {
    14         cap>>frame;//等价于cap.read(frame);
    15         if(frame.empty())//如果某帧为空则退出循环
    16             break;
    17         imshow("video", frame);
    18         waitKey(20);//每帧延时20毫秒
    19     }
    20     cap.release();//释放资源
    21 }

      三、读取视频说明

    1. 打开的视频可以是本地视频如: 
      VideoCapture cap(“1.avi”); 
      也可以是网络视频如: 
      VideoCapture cap(“http://www.laganiere.name/bike.avi“);
    2. 读取视频一定要加异常判断 
      A.打开视频失败(各种原因) 
      B. 取帧失败异常(程序结尾判断) 
      ex1: 
      if(!cap.isOpened()) //检查打开是否成功 
      return; 
      ex2: 
      cap>>frame; 
      if(!frame.empty()) //判断当前 帧是否为空 

      imshow(“video”, frame); 
      waitKey(30); 

      else break;

      四、获取指定视频类的相关参数信息

     1 #include<opencv2/opencv.hpp>
     2 #include<iostream>
     3 using namespace cv;
     4 using namespace std;
     5 
     6 void main(){
     7     VideoCapture cap;
     8     cap.open("E:\2.avi"); //打开视频,等价于   VideoCapture cap("E://2.avi");
     9 
    10     if(!cap.isOpened())
    11         return;
    12 
    13     int width = cap.get(CV_CAP_PROP_FRAME_WIDTH);  //帧宽度
    14     int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //帧高度
    15     int frameRate = cap.get(CV_CAP_PROP_FPS);  //帧率 x frames/s
    16     int totalFrames = cap.get(CV_CAP_PROP_FRAME_COUNT); //总帧数
    17 
    18     cout<<"视频宽度="<<width<<endl;
    19     cout<<"视频高度="<<height<<endl;
    20     cout<<"视频总帧数="<<totalFrames<<endl;
    21     cout<<"帧率="<<frameRate<<endl;
    22 
    23     Mat frame;
    24     while(1)
    25     {
    26         cap>>frame;//等价于cap.read(frame);
    27         if(frame.empty())
    28             break;
    29         imshow("video", frame);
    30         if(waitKey(20)>0)
    31             break;
    32     }
    33     cap.release();
    34 }

      五、读取摄像头

    读取摄像头和读取视频大同小异,主要是这句代码有些许不同。 
    VideoCapture cap; 
    cap.open(0); 
    读取视频时可以传入视频路径,而读取摄像头传入的是index索引号。


    注: 
    1)如果默认笔记本/台式机只有一个USB摄像头,Index=0; 如果有2个,一般Index为0和1,根据具体情况区分,摄像头接入和断开会改变Index值 
    2)如果接入2个以上,但只想用指定的一个,可以在设备管理器中禁用其他,同时Index设置为0 

    3)因为开启摄像头后一直在进行读取,所以需要用waitKey()返回值判断退出预览 
    imshow(“video”, frame); 
    if(waitKey(30)>0)//无按键按下返回-1,按键按下时退出 
    break; 
    也可以指定按键退出: 
    if(waitKey(30)==27) //Esc键退出,ESC的ASCLL码为27 
    break;

      六、读取摄像头后加入简单处理效果

    如果只是读取摄像头不进行处理的话,那毫无意义,现在以canny边缘检测以及颜色空间转换为目标进行处理。

     1 #include<opencv2/opencv.hpp>
     2 using namespace cv;
     3 
     4 void main(){
     5     VideoCapture cap;
     6     cap.open(0); //打开摄像头
     7 
     8     if(!cap.isOpened())
     9         return;
    10 
    11     Mat frame;
    12     while(1)
    13     {
    14         cap>>frame;//等价于cap.read(frame);
    15         Canny(frame, frame, 30, 100);//canny边缘检测,去掉这一行就是纯粹的读取摄像头了
    16         //cvtColor(frame, frame, CV_BGR2HSV);//BGR空间转为HSV颜色空间,注意,两者不能同时对同一张图片(在此为frame)进行处理,否则报错
    17         if(frame.empty())
    18             break;
    19         imshow("video", frame);
    20         if(waitKey(20)>0)//按下任意键退出摄像头  因电脑环境而异,有的电脑可能会出现一闪而过的情况
    21             break;
    22     }
    23     cap.release();
    24     destroyAllWindows();//关闭所有窗口
    25 }

    针对第20行代码:最开始电脑配置的opencv2.x版本,上述代码打开摄像头没有问题;后来使用opencv3.x版本,重新编译了contrib包,发现摄像头打开后一闪而过。

    原因是 waitkey() 如果不按键的时候是返回 oxff,oxff无符号时是255,有符号时是-1。windows vs 的环境默认了这个为非符号数 即255,而opencv的有些配置环境中是-1。

    解决方案:把原始代码中循环读取帧的

    if (waitKey(20)>=0)  break;

    改为

    if (waitKey(20) != 255)  break;

    或者把waitkey的返回值用有符号数去读取。

    uchar c=waitkey(20);  if(c!=255)  break;

      七、写入视频

      1、介绍

    ①VideoWriter: OpenCV提供VideoWriter类写视频文件,类的构造函数可以指定文件名、播放帧率、帧尺寸、是否创建彩色视频。 

    ②两种写入帧方法: 
    1 ) writer.write(frame); 
    2)writer >>frame(这里的箭头方向应该相反,不知道为什么箭头不能向←); 
    ③注意事项: 
    1)写入视频前需安装对应的编解码器 
    2)生成视频是否支持彩色应与构造函数设置一致 
    3)生成视频尺寸需与读取视频尺寸一致

      2、代码示例

     1 #include<opencv2/opencv.hpp>
     2 #include<iostream>
     3 using namespace cv;
     4 using namespace std;
     5 
     6 void main(){
     7     VideoCapture cap;
     8     cap.open("E://2.avi");
     9     Size size0=Size(cap.get(CV_CAP_PROP_FRAME_WIDTH),cap.get(CV_CAP_PROP_FRAME_HEIGHT));
    10     VideoWriter writer("E://out.avi",-1,cap.get(CV_CAP_PROP_FPS),size0,false);
    11 
    12     if(!cap.isOpened())
    13         return;
    14 
    15     Mat frame;
    16     while(1)
    17     {
    18         cap>>frame;
    19         Canny(frame,frame,30,100);
    20         if(frame.empty())
    21             break;
    22         writer<<frame;//等同于writer.write(frame);
    23         imshow("video", frame);
    24         if(waitKey(10)>0)
    25             break;
    26     }
    27     cout<<"write end!";
    28     cap.release();
    29     destroyAllWindows();
    30 }
  • 相关阅读:
    使用System.Web.Mail通过需验证的邮件服务器发送邮件(转) dodo
    报错显示"从客户端检测到有潜在危险的Request.Form 值" dodo
    setting页面出现的原理 dodo
    action的原理 dodo
    dnn一些公用方法分析 dodo
    缓存依赖概述 dodo
    在Intranet环境中保护.NETWeb应用程序方案(转) dodo
    dnn中的用户密码设置 dodo
    Application_Start事件中修改配置文件内容 dodo
    “System.Data.OleDb.OleDbException: 未指定的错误” dodo
  • 原文地址:https://www.cnblogs.com/little-monkey/p/7162340.html
Copyright © 2020-2023  润新知