在 OpenCV 中读取和写入视频与读取和写入图像非常相似。视频只不过是一系列通常称为帧的图像。因此,您需要做的就是遍历视频序列中的所有帧,然后一次处理一帧。在这篇文章中,我们将演示如何从文件、图像序列和网络摄像头读取、显示和写入视频。我们还将调查过程中可能出现的一些错误,并帮助了解如何解决它们。
开发步骤:
1.首先导入头文件
// Include Libraries #include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv;
2.从文件中读取视频
下面的下一个代码块使用VIDEOCAPTUREOCAPTUREOCAPTURE对象,然后我们将使用它来读取视频
文件.使用此类的语法如下所示:
VIDEOCAPTURE(PATH, APIPREFERENCE)
第一个参数是视频文件的文件名/路径.第二个是可选参数,表示APT偏好.与此可选参数相关的一些选项
将在下面进一步讨论.要了解更多信息APIPREFERENCE,请访问官方文档链接VIDEOCAPTUREAPLS.
# Create a video capture object, in this case we are reading the video from a file VideoCapture vid_capture("Resources/Cars.mp4");
现在我们有了一个视频捕获对象,我们可以使用该ISOPENEDO方法来确认视频文件是否已成功打开.该ISOPENED0方法这回一个布尔值,指示视频流是否有效.否则,您将收到一条错误消息可能暗示很多事情.其中之一是整个视频已损坏,或某些帧已损坏,假设视频文件已成功打开,我们可以使用该8ET0方法检索与视频流相关的重要元数据.请注意,此方法不适用于网络摄像头.该方法从此处GETO记录的选项枚举列表中获取单个参数.在下面的示例中,我们提供了数值5和7,它们对应于帧速率(CAP_PROP_FPS)和帧数(CAP_PROP_FRAME_COUNT).可以提供数值或名称.
if (!vid_capture.isOpened()) { cout << "Error opening video stream or file" << endl; } else { // Obtain fps and frame count by get() method and print int fps = vid_capture.get(5): cout << "Frames per second :" << fps; frame_count = vid_capture.get(7); cout << "Frame count :" << frame_count; }
在检索到与视频文件关联的所需元数据后,我们现在准备从文件中读取每个图像帧.这是通过创建一个循.环并使用该VID_CAPTURE.READ()方法从视频流中一次读取一帧来完成的.
该VIDLCAPTURE.TEADO方法返回一个元组,其中第一个元素是布尔值,下一个元素是实际的视频帧.当第一个元素为TRUE时,表示视频流包含要读取的帧.如果有要读取的帧,则可以使用IMSHOWO在窗口中显示当前帧,否则退出循环.请注意,您还使用该WAITKEY()函数在视频帧之间暂停20毫秒.调用该WAITKEY()函数可让您监视建盘以获取用户输入.在这种
情况下,例如,如果用户按下Q'键,则退出循环.
while (vid_capture.isOpened()) { // Initialize frame matrix Mat frame; // Initialize a boolean to check if frames are there or not bool isSuccess = vid_capture.read(frame); // If frames are present, show it if(isSuccess == true) { //display frames imshow("Frame", frame); } // If frames are not there, close it if (isSuccess == false) { cout << "Video camera is disconnected" << endl; break; } //wait 20 ms between successive frames and break the loop if key q is pressed int key = waitKey(20); if (key == 'q') { cout << "q key is pressed by the user. Stopping the video" << endl; break; } }
3.读取图像序列
处理来自图像序列的图像帧与处理来自视频流的帧非常相似。只需指定正在读取的图像文件。
在下面的示例中,
- 您继续使用视频捕捉对象
- 但您无需指定视频文件,只需指定图像序列
- 使用下面显示的符号 (Cars%04d.jpg),其中 %04d 表示四位序列命名约定(例如 Cars0001.jpg、Cars0002.jpg、Cars0003.jpg 等)。
- 如果您指定了“Race_Cars_%02d.jpg”,那么您将寻找以下形式的文件:
(Race_Cars_01.jpg、Race_Cars_02.jpg、Race_Cars_03.jpg 等……)。
VideoCapture vid_capture("Resources/Image_sequence/Cars%04d.jpg");
4.终极代码
// Include Libraries #include<opencv2/opencv.hpp> #include<iostream> // Namespace to nullify use of cv::function(); syntax using namespace std; using namespace cv; int main() { // initialize a video capture object VideoCapture vid_capture("Resources/Cars.mp4"); // Print error message if the stream is invalid if (!vid_capture.isOpened()) { cout << "Error opening video stream or file" << endl; } else { // Obtain fps and frame count by get() method and print // You can replace 5 with CAP_PROP_FPS as well, they are enumerations int fps = vid_capture.get(5); cout << "Frames per second :" << fps; // Obtain frame_count using opencv built in frame count reading method // You can replace 7 with CAP_PROP_FRAME_COUNT as well, they are enumerations int frame_count = vid_capture.get(7); cout << " Frame count :" << frame_count; } // Read the frames to the last frame while (vid_capture.isOpened()) { // Initialise frame matrix Mat frame; // Initialize a boolean to check if frames are there or not bool isSuccess = vid_capture.read(frame); // If frames are present, show it if(isSuccess == true) { //display frames imshow("Frame", frame); } // If frames are not there, close it if (isSuccess == false) { cout << "Video camera is disconnected" << endl; break; } //wait 20 ms between successive frames and break the loop if key q is pressed int key = waitKey(20); if (key == 'q') { cout << "q key is pressed by the user. Stopping the video" << endl; break; } } // Release the video capture object vid_capture.release(); destroyAllWindows(); return 0; }