索引地址:系列索引
基础篇的文章处理的对象都是读取的一张图片,那么高级篇的第一篇就是连续图片,即视频。视频分为两种一种是本地视频,类似于Mp4/mkv文件,另一种是从摄像头、rtsp读取的实时视频流。
读取并显示本地视频VideoCaptur()函数原型:
1 2 3 VideoCapture::VideoCapture () VideoCapture::VideoCapture (const string& filename) VideoCapture::VideoCapture (int device)
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 #include <opencv2/opencv.hpp> using namespace cv;int main () { VideoCapture capture ("1.avi" ) ; while (1 ) { Mat frame; capture >> frame; if (frame.empty ()) { break ; } imshow ("Video" , frame); waitKey (30 ); } return 0 ; }
从程序所在的文件夹中读取名称为1.avi的视频文件,然后显示在界面上,视频播放完毕后自动退出程序.
读取并显示摄像头摄像头功能是使用设备id,摄像头的默认id为0.
只需要将上面的代码修改一下就可以了.
1 2 VideoCapture capture (0 ) ;
opencv视频部分使用的是FFmpeg。
效果如下:
获取视频属性信息1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 #include <opencv2/opencv.hpp> #include <iostream> using namespace std;using namespace cv;int main () { VideoCapture capture; capture.open ("beat.mp4" ); if (!capture.isOpened ()){ std::cout << "fail to open video!" << std::endl; return -1 ; } long nTotalFrame = capture.get (CV_CAP_PROP_FRAME_COUNT); std::cout << "nTotalFrame = " << nTotalFrame << std::endl; int frameHeight = capture.get (CV_CAP_PROP_FRAME_HEIGHT); int frameWidth = capture.get (CV_CAP_PROP_FRAME_WIDTH); std::cout << "frameHeight = " << frameHeight << std::endl; std::cout << "frameWidth = " << frameWidth << std::endl; double FrameRate = capture.get (CV_CAP_PROP_FPS); std::cout << "FrameRate = " << FrameRate << std::endl; cv::Mat frameImg; long nCount = 1 ; while (true ){ std::cout << " Current frame: " << nCount << std::endl; capture >> frameImg; if (!frameImg.empty ()){ imshow ("frameImg" , frameImg); } else { break ; } if (char (waitKey (1 )) == 'q' ){ break ; } nCount++; } capture.release (); return 0 ; }
测试结果为:
1 2 3 4 5 6 7 8 9 10 nTotalFrame = 7522 frameHeight = 480 frameWidth = 852 FrameRate = 25 Current frame: 1 Current frame: 2 Current frame: 3 Current frame: 4 Current frame: 5 ...
保存至本地视频文件简单读取和显示以及操作介绍完毕,能读就可以写,下面介绍将读取的帧在写入视频容器中。
流程为:
获取视频信息 分离每帧的RGB通道 保存B通道数据为新视频 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 #include <iostream> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std;using namespace cv;int main () { string sourceVideoPath = "1.mp4" ; string outputVideoPath = "2.mp4" ; VideoCapture inputVideo (sourceVideoPath,CAP_FFMPEG) ; if (!inputVideo.isOpened ()) { cout << "fail to open!" << endl; return -1 ; } VideoWriter outputVideo; cv::Size videoResolution = cv::Size ((int )inputVideo.get (CAP_PROP_FRAME_WIDTH), (int )inputVideo.get (CAP_PROP_FRAME_HEIGHT)); double fps = inputVideo.get (CAP_PROP_FPS); cout << "totalFrame:" << inputVideo.get (CAP_PROP_FRAME_COUNT) << endl; cout << "fps:" << inputVideo.get (CAP_PROP_FPS) << endl; cout << "videoResolution:" << videoResolution.width << " " << videoResolution.height << endl; outputVideo.open (outputVideoPath, CAP_FFMPEG, 25.0 , videoResolution, true ); if (!outputVideo.isOpened ()) { cout << "fail to open!" << endl; return -1 ; } cv::Mat frameImg; int count = 0 ; std::vector<cv::Mat> rgb; cv::Mat resultImg; for (int i = 0 ; i < 30 ; i++) { inputVideo >> frameImg; if (!frameImg.empty ()) { count++; cv::imshow ("frameImg" , frameImg); cv::split (frameImg, rgb); for (int i = 0 ; i < 3 ; i++) { if (i != 0 ) { rgb[ i ] = cv::Mat::zeros (videoResolution, rgb[ 0 ].type ()); } cv::merge (rgb, resultImg); } cv::imshow ("resultImg" , resultImg); outputVideo << resultImg; } else { break ; } if (char (waitKey (1 )) == 'q' ) { inputVideo.release (); outputVideo.release (); break ; } } std::cout << "writeTotalFrame:" << count << std::endl; inputVideo.release (); outputVideo.release (); return 0 ; }
编译运行,会报错
1 OpenCV: FFMPEG: tag 0x0000076c/'l???' is not found (format 'avi / AVI (Audio Video Interleaved)' )'
将写部分修改为
1 outputVideo.open (outputVideoPath, VideoWriter::fourcc ('M' ,'J' ,'P' ,'G' ), 25.0 , videoResolution, true );
再次编译运行
输出结果为:
1 2 3 4 5 6 totalFrame:2530 fps:8.04132 videoResolution:1610 1030 OpenCV: FFMPEG: tag 0x47504a4d/'MJPG' is not supported with codec id 7 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV: FFMPEG: fallback to use tag 0x7634706d/'mp4v' writeTotalFrame:30
视频效果为:
我们拆分的是B通道,即Blue部分。
保存的文件为