videocapture 保存图片_RoboMaster视觉教程OpenCV(二)读取视频图像与转换

这篇教程介绍了如何使用OpenCV在RoboMaster比赛中读取视频和图像,包括保存视频和图片的例程。讲解了VideoCapture、VideoWriter、waitKey()、帧率等相关概念,并提供了保存视频和图片的代码示例。
摘要由CSDN通过智能技术生成

RoboMaster视觉教程OpenCV(二)读取视频图像与转换

在Robomaster比赛中,读取视频或者图像是极其重要的。因为我们需要在热身赛的时候用摄像头保存一段视频或者图片。之后根据视频中的光线来调节摄像头曝光。此外,也可能需要将视频分解成图片来做数据集,或者说将多个图片合成一段视频。所以这一节的内容就是为这个做准备的。

RoboMaster视觉教程OpenCV(二)读取视频图像与转换一 基本概念二 打开摄像头保存视频例程2.1 waitkey()2.2 帧率2.3 VideoCapture()三 打开摄像头保存图片例程3.1 代码框架3.2 图片命名四 任务4.1 任务参考代码微信公众号

一 基本概念

读于仕琪《open cv入门教程》的前四章,读毛星云的书:《open cv3编程入门》P34-P40,P65-P70

了解基本概念。(回复opencv2可收到这两本书链接)

之后学习两个例程:打开摄像头保存视频和打开摄像头保存图片

二 打开摄像头保存视频例程

#include #include "opencv2/opencv.hpp"/*opencv.hpp包含了Opencv各模块的头文件,如高层GUI图形用户界面模块头文件highgui.hpp,图像处理模块头文件imgprogc.hpp等。所以,用“#include”即可,达到精简代码的作用。*/

using namespace std;

using namespace cv;

int main(int argc, char** argv)//或者char* argv[]{

//0表示打开笔记本上第一个摄像头 VideoCapture cap(0);

// VideoCapture cap(0); //检查是否成功打开 if(!cap.isOpened())

{

cerr << "Can not open a camera or file." << endl;

//此处用了cerr,而不是cout。cerr对象又叫标准错误,通常用来输出警告和错误信息给程序的使用者。无 //缓存 return -1;

}

//定义视频的宽度和高度 Size s(640, 480);//宽在前,高在后 //创建 writer,并指定 FOURCC 及 FPS 等参数 VideoWriter writer = VideoWriter("myvideo.avi",CV_FOURCC('M','J','P','G'), 25, s);

//检查是否成功创建 if(!writer.isOpened())

{

cerr << "Can not create video file.\n" << endl;

return -1;

}

//视频帧 Mat frame(s, CV_8UC3);

for(;;)//等价于while(1) {

//从 cap 中读一帧,存到 frame cap >> frame;

//如果未读到图像 if(frame.empty())

break;

//显示结果 imshow("pictures", frame);

writer << frame;

//等待 30ms,如果按键则退出循环 if(waitKey(30) >= 0)

break;

}

//cap.release(); //writer.release();以前需要释放类,但是现在不需要release,会自动释放的 //退出时会自动释放 cap 中占用资源 return 0;

}

上面的代码实现了打开笔记本自带的摄像头。将摄像头的内容显示出来,并且保存为一个视频。

代码的执行过程参照OpenCV(一)测试open cv时候的操作,使用g++指令。 执行代码之后,在命令行输入

xdg-open myvideo.avi

可以查看生成的myvideo.avi视频,xdg-open是Ubuntu自带的打开命令,除视频外还可以打开图片,文档等等

注意:Size s(640, 480);Mat类,VideoWrite类和摄像头硬件这三者的分辨率一定要一致。否则视频只有6kb,无法打开。(Mat默认)

2.1 waitkey()

这个函数是opencv里的,和imshow()配合,使用waitKey(30)代表在屏幕上显示imshow()的图像30毫秒。

30ms后自动关闭显示。用在循环里,也就是每一个循环处理一帧图像,每一帧图像显示30毫秒。

同时,该函数返回值为当前键盘按下的值(是int),没有按键时返回-1。 所以,代码中一旦有键盘上的键按下,那么waitkey(30)这个函数返回的数值就是这个英文字母代表的ASCII码值。满足条件,break跳出循环。

2.2 帧率

最高帧率由设备决定,实际帧率由程序决定

最高帧率:摄像头设备打开后会不断地刷新当前图像,这个刷新的频率即是最高帧率,由设备的硬件限定。

实际帧率:假设设备的最高帧率为25帧,那么每帧的时间间隔为40ms,当程序读取处理每帧耗费的时间超过 40ms时,帧率就会低于25帧;假设程序读取一帧并进行处理耗费100ms,则实际帧率为10。

关于实际帧率的计算,必须从获取一个帧开始,到获取下一帧结束。如果需要对图像进行复杂处理,而又 不希望影响到帧率,可以先把图像保存在内存中,另开线程进行处理。经验证,显示图像及保存视频文件函数 耗时较少,对帧率基本没有影响,保存图像文件函数耗时较多,会对帧率有影响。

对于帧率的分析很有帮助,大家看一下

2.3 VideoCapture()

VideoCapture cap(0);()中的数字是摄像头的编号,该编号和摄像头的PID有关, PID越小,编号则越小,编号从0开始。笔记本会内置的摄像头设备编号是最小的,为0。 PID是硬件设备都有的编号。

三 打开摄像头保存图片例程

#include #include "opencv2/opencv.hpp"using namespace std;

using namespace cv;

int main(int argc, char** argv)

{

int d=0;

char ad[300]={0};

VideoCapture cap(0);

if(!cap.isOpened())

{

cerr << "Can not open a camera or file." << endl;

return -1;

}

Size s(640, 480);

Mat frame(s, CV_8UC3);

for(;;)

{

cap >> frame;

if(frame.empty())

break;

imshow("pictures", frame);

int k=waitKey(30);//延时30ms if(k=='e')

break;

else if(k=='c')

{

sprintf(ad, "./%d.png", ++d);

imwrite(ad, frame );

cout<

}

}

//退出时会自动释放 cap 中占用资源 return 0;

}

上面的代码实现了打开摄像头,显示摄像头拍到的内容,并且按照数字的顺序将,视频中的内容保存为图片。按c则拍照片,按e则退出。

3.1 代码框架

和上面的代码框架大体相同,只不过没有把从摄像头得到的图像真写入到视频里,而是把每一帧写成图像。得到的。打开摄像头,从摄像头读取一帧图像,将这帧图像保存为PNG图片。(png更好,一基本概念教程里有说)所不同的是我们要保存多个图片,图片的命名。有一定方法。同时,这里还用到了waitkey()返回值。

3.2 图片命名

imwrite(ad, frame );

教程中介绍imwrite函数( ,),两个参数,第一个用字符串表示,此处用了数组表示的字符串,代码图片要保存到的路径,路径中包含图片名字。第二个参数是mat类的对象。

每一次,imwrite()函数保存图片的路径都不同。这都源于sprintf()函数。

sprintf()最常见的应用之一莫过于把整数打印到字符串中,通过sprintf()函数,每一次保存图片都可以令图片名字不同,实现了保存多个图片的目的。

比如说,ad [] = "./%d.png" ./表示当前路径,%d这里的位置会被后边的int变量d替换,所以ad实际上是

./1.png ./2.png ./3.png

四 任务打开本机摄像头,学习并运行代码1,保存一段视频。写代码3,将视频中的每一帧拆为图片,要求格式为png,压缩级别为2,命名方式为1.png,2.png……

打开本机摄像头,学习并运行代码2,保存25张图片。写代码4,将这25张图片转化为一段视频,要求格式为.avi,帧率为5。

PS:任务的代码将在下一次更新时发布。

4.1 任务参考代码

matlab2016将图片合并为多个视频以及将视频拆分为多个图片

%将图片转化为视频

clear all;

clc;

srcDic = uigetdir('G:\smc\ljw');%此处更改路径,注意文件名前的不是'\'而是'/'

cd(srcDic);

allnames = struct2cell(dir('*.jpg'));%找到所有jpg文件

[k,len]=size(allnames);

aviobj = VideoWriter('example.avi');%在图片目录下会生成avi文件

aviobj.FrameRate = 2;%更改帧率

open(aviobj)

for i = 1:len

name = allnames{1,i};

frame = imread(name);

writeVideo(aviobj,frame);

end

close(aviobj)

%将视频转化成图片

v1=VideoReader('example.avi');%path

for i=1:v1.numberofframes

temp=read(v1,i);

%figure(i)

%imshow(temp);

str = strcat('output',int2str(i),'.jpg')

imwrite(temp,str);

end

%将图片转化为视频

clear all;

clc;

srcDic = uigetdir('C:\Users\UMECJF\Desktop\jpgc');

cd(srcDic);

allnames = struct2cell(dir('*.jpg'));

[k,len]=size(allnames);

aviobj = VideoWriter('example.avi');

aviobj.FrameRate = 10;

open(aviobj)

for i = 1:len

name = allnames{1,i};

frame = imread(name);

writeVideo(aviobj,frame);

end

close(aviobj)

微信公众号

欢迎大家关注我的个人公众号,现阶段主要总结Robomaster相关的计算机视觉知识。

公众号名称:三丰杂货铺

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值