赞
踩
最近看了一些C++中的流的概念。下面几句话,是自己结合看到的书和博文所得到的理解,阅历有限,欢迎留言指正哈!!!
1、C++中,由于类可以实例化创建对象,所以,其实类的实例化创建对象的过程就是创建流的过程。所以我们有时候也把类的实例化创建的对象叫做流对象。任何一个类都可以实例化创建对象,也即任何一个类都可以创建流(流对象),当然了,也要排除某些基类。
2、C++中的数据传递是靠 “流” 来实现的。流,也叫流对象,你就把类的实例化得到的对象叫做流(流对象),对象可以调用许多的方法,那么流(流对象)也可以调用许多的方法。这样理解的话,流的本质就是一个对象(流对象)。
3、在实现C++的数据传递过程中:一般地,流对象都要与某个具体的设备或者文件相联系起来。当流对象与某个具体的设备或文件相联系起来之后,此时,对流对象的操作就等价于是对某个设备或文件的操作,对某个设备或文件的操作就等价于是对流对象的操作。这种操作关系可以简化成:流对象=某个具体的设备或文件
经常接触到的,C++中的流主要分成三类:
- 标准I/O流:“标准”的意思就是,默认的程序输入是指从键盘输入,默认的程序输出是指输出到屏幕。
- 文件I/O流:程序输入是指从文件读取数据,程序输出是指把数据写入文件。
- 字符串I/O流:程序输入是指从字符串中读取数据,程序输出是指把数据写入字符串中。
4、从“流”的观点来理解C++中的 cin >> x 和 cout << y 的含义:
- cin >> x :由于“cin”是一个标准输入流对象,而“>>”是流中的提取运算符。因为在头文件istream中创建“cin”标准输入流对象时,就已经把该流对象与某个具体的设备(这里指键盘)建立了联系,所以,对输入流对象“cin”的操作就等价于是对键盘的操作,对键盘的操作就等价于是对输入流对象“cin”的操作。这里的含义是,从输入流对象“cin”中去提取数据,然后把从输入流对象“cin”中提取出来的数据赋值给程序中的x变量(也即,从键盘输入中去提取数据,然后把从键盘输入中提取出来的数据赋值给程序中的x变量)。
- cout << y :由于“cout”是一个标准输出流对象,而“<<”是流中的插入运算符。因为在头文件ostream中创建“cout”标准输出流对象时,就已经把该流对象与某个具体的设备(这里指屏幕)建立了联系,所以,对输出流对象“cout”的操作就等价于是对屏幕的操作,对屏幕的操作就等价于是对输出流对象“cout”的操作。这里的含义是,把程序中y变量的值插入到输出流对象“cout”中去,(也即,把程序中y变量的值插入到屏幕中去)。
5、OpenCV中,视频数据的读取、图像序列的读取、摄像头的调用,三者都是使用的 cv::VideoCapture类,该类的作用是创建一个 视频流对象(包括输入视频流对象和输出视频流对象);下面的视频,你就要把它理解成一个文件,视频文件。
#include<iostream> #include<opencv2\opencv.hpp> using namespace std; using namespace cv; int main() { //cv::VideoCapture video_capture;//默认构造,创建视频流video_caputure,但此时视频流还没有与某个具体的视频文件相联系 //video_capture.open("C:/Users/Administrator/Desktop/testVideo.mp4");//视频流调用open方法打开了testVideo.mp4视频,表示video_capture视频流已经与testVideo.mp4视频文件建立联系了。此时,对video_capture视频流的操作就等价于是对testVideo.mp4文件的操作,对testVideo.mp4文件的操作就等价于是对video_capture视频流的操作。 //也可以带参构造,创建视频流video_caputure,上面默认构造的区别是:使用带参构造创建的视频流video_caputure已经与某个具体的视频文件testVideo.mp4建立联系了,因为带参构造函数中会去自动调用open函数,去建立视频流video_caputure与具体视频文件test.Video.mp4的联系。此时,对video_capture视频流的操作也就等价于是对testVideo.mp4文件的操作,对testVideo.mp4文件的操作也就等价于是对video_capture视频流的操作。 cv::VideoCapture video_capture("C:/Users/Administrator/Desktop/testVideo.mp4"); //判断视频是否读取成功 if (video_capture.isOpened()) { cout << "视频读取成功" << endl; cout << "视频文件的当前位置=" << video_capture.get(CAP_PROP_POS_MSEC) << endl; cout << "视频流中图像的宽度=" << video_capture.get(CAP_PROP_FRAME_WIDTH) << endl; cout << "视频流中图像的高度=" << video_capture.get(CAP_PROP_FRAME_HEIGHT) << endl; cout << "视频流中图像的帧率=" << video_capture.get(CAP_PROP_FPS) << endl; cout << "视频流中图像的帧数=" << video_capture.get(CAP_PROP_FRAME_COUNT) << endl; } else { cout << "视频读取失败" << endl; return 0; } //获取视频中的图像 while (1) {//循环:将视频流中的图像一帧一帧的赋值给Mat对象 cv::Mat frame; video_capture >> frame;//重点,从视频流对象video_capture中提取数据(图像),并将提取出来的数据赋值给frame if (frame.empty()) {//true说明视频流的图像已经提取完啦 cout << "视频流的图像已经读取完啦" << endl; break; } // cv::namedWindow("myWindow");//创建窗口 cv::imshow("myWindow", frame); //cv::waitKey(1000);//暂停1000ms,即显示一帧之后,停顿一秒 cv::waitKey(1000 / video_capture.get(CAP_PROP_FPS));//即为帧率的速度 } return 0; }
运行结果
有时候,我们从数据库中下载下来的数据,有些直接是视频,而有些是一帧一帧的图像,就比如下面的这种情况:
方法一:将每个图片的文件名按顺序存放在一个文本文件中,然后可以从文本文件中逐个提取文件名。
方法二:先将数字0015转化成字符串“0015”,然后再把字符串“0015”与字符串“frame_”和字符串“.jpg”一块拼凑成一个新的字符串“frame_0015.jpg”(即为图像的名字),最后再采取读取图像的方式逐一读取文件夹下的所有图像。
殊不知,在OpenCV中可以直接使用 VideoCapture类 来读取图像序列的。
#include<iostream> #include<opencv2/opencv.hpp> using namespace std; using namespace cv; int main() { //图像名称frame_0015.jpg:采用"前缀+%04d+后缀"的形式,这里为"frame_%04d.jpg"; //图像名称frame_015.jpg:采用"前缀+%03d+后缀"的形式,这里为"frame_%03d.jpg"; //图像名称frame_15.jpg:采用"前缀+%02d+后缀"的形式,这里为"frame_%02d.jpg"; //图像名称frame0015.jpg:采用"前缀+%04d+后缀"的形式,这里为"frame%04d.jpg"; //图像名称frame015.jpg:采用"前缀+%03d+后缀"的形式,这里为"frame%03d.jpg"; //图像名称frame15.jpg:采用"前缀+%02d+后缀"的形式,这里为"frame%02d.jpg"; string first_image = "C:/....../frame_%04d.jpg"; cv::VideoCapture image_sequence(first_image);//image_sequence:图像序列流 if (image_sequence.isOpened()) { cout << "图像序列读取成功" << endl; } else { cout << "图像序列读取失败" << endl; return -1; } //获取图像序列中的图像 while (1) {//循环:将图像序列中的图像一帧一帧的赋值给Mat对象 cv::Mat frame; image_sequence >> frame;//重点,从图像序列流中提取数据(图像),并将提出出来的数据帧赋值给frame if (frame.empty()) {//true说明图像序列中的图像已经提取完啦 cout << "图像序列中的图像已经读取完啦" << endl; break; } // cv::namedWindow("myWindow");//创建窗口 cv::imshow("myWindow", frame); cv::waitKey(1000);//暂停1000ms,即显示一帧之后,停顿一秒 } return 0; }
1、调用摄像头与读取视频文件相比,只有一行代码不同;
2、从摄像头中读取图像数据的方式与视频中读取图像数据的方式相同,都是通过 “>>” 符号读取当前时刻相机拍摄到的图像。
#include<iostream> #include<opencv2\opencv.hpp> using namespace std; using namespace cv; int main() { //cv::VideoCapture video_capture;//默认构造,创建视频流 //video_capture.open("C:/Users/Administrator/Desktop/testVideo.mp4");//将视频流与某个具体的视频文件联系起来 //也可以带参构造,创建视频流,构造函数中自动调用open函数,将视频流与某个具体的视频文件联系起来 //cv::VideoCapture video_capture("C:/Users/Administrator/Desktop/testVideo.mp4"); //调用摄像头 cv::VideoCapture video_capture(0);//设备的第一个摄像头 //判断视频是否读取成功 if (video_capture.isOpened()) { cout << "视频读取成功" << endl; cout << "视频文件的当前位置=" << video_capture.get(CAP_PROP_POS_MSEC) << endl; cout << "视频流中图像的宽度=" << video_capture.get(CAP_PROP_FRAME_WIDTH) << endl; cout << "视频流中图像的高度=" << video_capture.get(CAP_PROP_FRAME_HEIGHT) << endl; cout << "视频流中图像的帧率=" << video_capture.get(CAP_PROP_FPS) << endl; cout << "视频流中图像的帧数=" << video_capture.get(CAP_PROP_FRAME_COUNT) << endl; } else { cout << "视频读取失败" << endl; return 0; } //获取视频中的图像 while (1) {//循环,将视频流中的图像一帧一帧的赋值给Mat对象 cv::Mat frame; video_capture >> frame; //从视频流中提数据(图像),并将提取出来的数据赋值给frame if (frame.empty()) {//true说明已经是视频流的图像已经提取完啦 cout << "视频流中的图像已经读取完啦" << endl; break; } // cv::namedWindow("myWindow"); cv::imshow("myWindow", frame); //cv::waitKey(1000);//暂停1000ms,即显示一帧之后,停顿一秒 cv::waitKey(1000 / video_capture.get(CAP_PROP_FPS));//即为帧率的速度 } return 0; }
运行结果
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。