Opencv打开摄像头并按格式保存视频和每帧图片以及连续帧的图片和视频相互转化(C++版本和Python版本)

一、VideoCapture()类的常用API接口

1.构造VideoCapture()对象实例

C++版本

cv::VideoCapture::VideoCapture(const string&   filename);  //input filename
cv::VideoCapture::VideoCapture(int device);   //video capture denice id
cv::VideoCapture::VideoCapture();

Python版本

cap=cv2.VideoCapture(filename)
cap=cv2.VideoCapture(device)
cap=cv2.VideoCapture()

功能:
创建一个VideoCapture类的实例,如果传入对应的参数,可以直接打开视频文件或者要调用的摄像头。

参数:
filename代表视频文件的路径,这时会打开指定路径下的视频(.avi,.mpg,.mp4)等等,也可以是图片序列(.jpg文件序列)或者视频流的网址。请注意,每个视频流或IP摄像机源均具有其自己的URL方案。

device为整型变量,参数是0,表示打开笔记本的内置摄像头;参数是1,则打开外置摄像头;其他数字则代表其他设备。通常来说,它是区分不同摄像头的一个标识码,如果在当前系统下只有一个摄像头时参数为0,当有多个摄像头同时处于当前系统之中时,参数随之递增即可。参数为 -1时单独出现窗口,选取相应编号摄像头。

备注:
对于C++版本,也可以先对对象进行实例化,再使用open函数初始化。

bool cv::VideoCapture::open(const string& filename);
bool cv::VideoCapture::open(int device);
bool cv::VideoCapture::isOpened();

功能:对已经定义的VideoCapture类的实例进行初始化,传入对应的参数,可以直接打开视频文件或者要调用的摄像头。

参数:与前面构建对象实例的参数相同。如果成功读取视频或者调用摄像头则返回true,否则返回false。

这样我们有两种方法构建VideoCapture()对象实例

//先实例化再初始化
cv::VideoCapture capture;
capture.open("cat.avi");
//同时实例化和初始化
cv::VideoCapture capture("cat.avi");

2.利用VideoCapture()读取图片

C++版本

bool cv::VideoCapture::grab();
bool cv::VideoCapture::retrieve(Mat& image, int channel=0);

VideoCapture& cv::VideoCapture::operator>>(Mat& image);
bool cv::VideoCapture::read(Mat& image);

grab() 功能:从视频文件或捕获设备中抓取下一个帧,假如调用成功返回true。

retrieve() 功能:解码并且返回刚刚抓取的视频帧,假如没有视频帧被捕获(相机没有连接或者视频文件中没有更多的帧)将返回false。

read() 功能:该函数结合grab()和retrieve()其中之一被调用,用于捕获、解码和返回下一个视频帧。假如没有视频帧被捕获(相机没有连接或者视频文件中没有更多的帧)将返回false。

这样C++版本有四种读取方式

capture.read(frame); 
 
capture.grab(); 
 
capture.retrieve(frame); 
 
capture >> frame;

Python版本

ret,image=cap.read()

功能:cap.read()按帧读取视频,ret,frame是获cap.read()方法的两个返回值。其中ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。frame就是每一帧的图像,是个三维矩阵。

3.利用VideoCapture()获取和设置摄像头或者视频参数信息

C++版本

double cv::VideoCapture::get(int propid);  //property identfier(see table)
bool cv::VideoCapture::set(int propid, double value);

Python版本`

value=cap.get(propid)
cap.set(propid,value)

功能:我们通过get()和set()函数分别可以获取和设置摄像头或者视频参数信息,

参数:包括的参数信息如下表:
在这里插入图片描述

4.释放VideoCapture()对象

C++版本

void cv::VideoCapture::release();

Python版本

cap.release()

功能:关闭视频文件或者摄像头。

二、VideoWriter()类的常用API接口

1.构造VideoWriter()对象实例

C++版本

cv::VideoWriter::Videowriter(const String &filename, int fourcc, double fps, Size frameSize, bool isColor=true);
cv::VideoWriter::VideoWriter(const String &filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor=true);
cv::VideoWriter::Videowriter();

Python版本

out=cv2.VideoWriter(filename, fourcc, fps, frameSize,isColor=true)
out=cv2.VideoWriter()

功能:创建一个VideoWriter类的实例。

参数:
filename输出视频文件的名称。

fourcc用于压缩帧视频轨道的编解码器的4个字符的代码。现在所有的视频解码器都有唯一的短名称,最多4个字符。常见的有XVID,DVIX和H264。
例如:
VideoWriter :: fourcc(‘P’,‘I’,‘M’,‘1’)是MPEG-1编解码器;
VideoWriter :: fourcc(‘M’,‘J’,‘P’,'G ')是动态jpeg编解码器等。
可以在FOURCC页面的“ 视频编解码器”中获取代码列表。带有MP4容器的FFMPEG后端本机使用其他值作为fourcc代码:请参见ObjectType,因此您可能会从OpenCV收到有关fourcc代码转换的警告消息。

fps代表创建的视频流的帧率,这是输出视频的每秒帧数。

frameSize代表视频帧的大小(长宽)。

isColor默认情况是True。如果为True,则编码器将期望并编码彩色帧,否则它将与灰度帧一起使用(仅Windows当前支持该标志)。

备注:
对于C++版本,也可以先对对象进行实例化,再使用open函数初始化。

bool cv::VideoWriter::open(const String &filename,int fourcc, double fps,Size frameSize,bool isColor=true);
bool cv::VideoWriter::open(const String &filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor=true);
bool cv::VideoWriter::isOpened();

功能:对已经定义的VideoWriter类的实例进行初始化,传入对应的参数。

参数:与前面构建对象实例的参数相同。如果成功打开视频编写器则返回true,否则返回false。

这样我们有两种方法构建VideoWriter()对象实例

int vedio_width = capture.get(cv::CAP_PROP_FRAME_WIDTH); 
int vedio_height = capture.get(cv::CAP_PROP_FRAME_HEIGHT);
std::string outputVideoPath = "..\\test.avi";
//先实例化再初始化
cv::VideoWriter video;
video.open(outputVideoPath,cv::VideoWriter::fourcc('M', 'P', '4', '2'), 25, cv::Size(vedio_width, vedio_height));
//同时实例化和初始化
cv::VideoWriter video(outputVideoPath,cv::VideoWriter::fourcc('M', 'P', '4', '2'), 25, cv::Size(vedio_width, vedio_height));

2.利用VideoWriter()写入视频

C++版本

VideoWriter& cv::VideoWriter::operator<<(Mat& image);
void cv::VideoWriter::write(InputArray image);

功能:将指定的图像写入视频文件。它的大小必须与打开视频编写器时指定的大小相同。通常,彩色图像应采用BGR格式。

这样C++版本有两种读取方式

video.write(frame); 

capture << frame;

Python版本

out.write(frame)

3.利用VideoWriter()获取和设置视频写入器属性

C++版本

double cv::VideoWriter::get(int propid);  //property identfier(see table)
bool cv::VideoWriter::set(int propid, double value);

Python版本`

value=out.get(propid)
out.set(propid,value)

功能:我们通过get()和set()函数分别可以获取和设置VideoWriter()属性标识符或视频I / O API后端的其他标志之一。

参数:这里的属性就不一一赘述了,大家可以去参考opencv官方文档中的cv :: VideoWriterProperties。

4.释放VideoWriter()对象

C++版本

void cv::VideoWriter::release();

Python版本

out.release()

功能:关闭视频文件或者摄像头。

三、打开摄像头并按格式保存视频和每帧图片

1.C++版本

#include <iostream>
#include<string.h>
#include<fstream>
#include<Windows.h>
#ifdef _WIN32
#define OPENCV
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <fstream>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
#include <math.h>
#include <opencv2/core/core.hpp>    
#include <opencv2/ml/ml.hpp>  

using namespace std;
using namespace cv;
using namespace ml;

int device = 1;
int i_begin = 0;
int width = 1280;
int height = 720;
double fps = 25.0;
std::string outputVideoPath = "test\\";
std::string outputVideoName = "test.avi";
std::string outputPicturePath = "Latest\\";
std::string outputPictureFormat = ".jpg";
std::string imshowWindowName = "result";
int quit = 'q';
int fourcc = cv::VideoWriter::fourcc('M', 'P', '4', '2');
int waitkey_time = 100;

int main()
{
	cv::VideoCapture capture(device);

	if (!capture.isOpened())                         //判断是否成功打开相机
	{
		return -1;
	}

	capture.set(cv::CAP_PROP_FRAME_WIDTH, width);  //设置捕获视频的宽度
	capture.set(cv::CAP_PROP_FRAME_HEIGHT, height);  //设置捕获视频的高度

	int vedio_width = capture.get(cv::CAP_PROP_FRAME_WIDTH);    //获取图像的宽度
	int vedio_height = capture.get(cv::CAP_PROP_FRAME_HEIGHT);  //获取图像的高度
	cv::VideoWriter video(outputVideoPath+ outputVideoName, fourcc, fps, cv::Size(vedio_width, vedio_height));
	while (true)
	{
		cv::Mat frame;
		capture >> frame;
		if (frame.empty())
			continue;
		cv::namedWindow(imshowWindowName, CV_WINDOW_NORMAL);
		cv::imshow(imshowWindowName, frame);
		cv::imwrite(outputPicturePath + to_string(i_begin) + outputPictureFormat, frame);
		i_begin++;
		video << frame;
		int q=cv::waitKey(waitkey_time);
		if (q == quit)
			break;
	}
	capture.release();
	video.release();
	cv::destroyAllWindows();
	return 0;
}

2.Python版本

import cv2

device=1
i_begin=0
width,height=1280,720
fps=25.0
outputVideoPath='test/'
outputVideoName='test.avi'
outputPicturePath='Latest/'
outputPictureFormat='.jpg'
imshowWindowName='result'
quit='q'
fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', '2')
waitkey_time = 100

cap=cv2.VideoCapture(device)
cap.set(cv2.CAP_PROP_FRAME_WIDTH,width)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT,height)
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
out=cv2.VideoWriter(outputVideoPath+outputVideoName, fourcc, fps, size)

while(cap.isOpened()):
    ret,image=cap.read()
    if ret==False:
        break
    
    cv2.namedWindow(imshowWindowName, cv2.WINDOW_NORMAL)
    cv2.imshow(imshowWindowName,image)
    cv2.imwrite(outputPicturePath+str(i_begin)+outputPictureFormat,image)
    i_begin+=1
    out.write(image)
    if cv2.waitKey(waitkey_time) & 0xFF==ord(quit):
        break
cap.release()
out.release()
cv2.destroyAllWindows()

3.参数说明

device为0表示打开笔记本的内置摄像头,device为1或更大,则打开外置摄像头或其他设备。

i_begin表示保存的每帧图片是从i_begin.jpg开始命名的,后面依次递增。

width,height为设置摄像头拍摄图片的宽度和高度。

fps为创建的视频流的帧率。

outputVideoPath和outputVideoName分别表示保存视频的路径和名称。

outputPicturePath和outputPictureFormat分别表示保存每一帧图片的路径和名称。

imshowWindowName表示显示每一帧图片窗口的名称。

quit表示该字符被按下,摄像头关闭。

fourcc表示压缩帧视频轨道的编解码器的4个字符的代码。

waitkey_time表示等待按键按下时间,也可以作为设置摄像间隔帧率的时间。

4.运行结果

在运行之前,我们需要在代码所在的目录下手动创建test和Latest两个文件夹。之后启用内置摄像头或插上外置摄像头,运行程序,将会跳出窗口,显示摄像头拍摄的内容。键盘输入q,则摄像头和窗口关闭。这时候会在test文件夹中找到保存的test.avi视频,在Latest文件夹中找到命名为0.jpg,1.jpg,2.jpg,…的连续帧图片。

四、视频转化为连续帧的图片

1.C++版本

#include <iostream>
#include<string.h>
#include<fstream>
#include<Windows.h>
#ifdef _WIN32
#define OPENCV
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <fstream>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
#include <math.h>
#include <opencv2/core/core.hpp>    
#include <opencv2/ml/ml.hpp>  

using namespace std;
using namespace cv;
using namespace ml;

std::string inputVideoPath = "sp\\";
std::string inputVideoName = "test.avi";
int i_begin = 0;
std::string outputPicturePath = "sq\\";
std::string outputPictureFormat = ".jpg";
std::string imshowWindowName = "result";
int quit = 'q';

int main()
{
	cv::VideoCapture capture(inputVideoPath+inputVideoName);

	if (!capture.isOpened())                         
	{
		return -1;
	}

	int vedio_width = capture.get(cv::CAP_PROP_FRAME_WIDTH);    //获取图像的宽度
	int vedio_height = capture.get(cv::CAP_PROP_FRAME_HEIGHT);
	float video_fps = capture.get(cv::CAP_PROP_FPS);
	cout << "width:" << vedio_width << '\n' << "height:" << vedio_height << '\n' << "fps:" << video_fps;
	int waitkey_time = int(1000 / video_fps);

	while (true)
	{
		cv::Mat frame;
		capture >> frame;
		if (frame.empty())
			break;
		cv::namedWindow(imshowWindowName, CV_WINDOW_NORMAL);
		cv::imshow(imshowWindowName, frame);
		cv::imwrite(outputPicturePath + to_string(i_begin) + outputPictureFormat, frame);
		i_begin++;
		int q = cv::waitKey(waitkey_time);
		if (q == quit)
			break;
	}
	capture.release();
	cv::destroyAllWindows();
	return 0;
}

2.Python版本

import cv2

inputVideoPath='sp/'
inputVideoName='test.avi'
i_begin=0
outputPicturePath='sq/'
outputPictureFormat='.jpg'
imshowWindowName='result'
quit='q'

cap=cv2.VideoCapture(inputVideoPath+inputVideoName)
vedio_width=int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
vedio_height=int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
vedio_fps=float(cap.get(cv2.CAP_PROP_FPS))
print("width:",vedio_width)
print("height:",vedio_height)
print("fps:",vedio_fps)
waitkey_time=int(1000/vedio_fps)

while(cap.isOpened()):
    ret,image=cap.read()
    if ret==False:
        break 
    cv2.namedWindow(imshowWindowName, cv2.WINDOW_NORMAL)
    cv2.imshow(imshowWindowName,image)
    cv2.imwrite(outputPicturePath+str(i_begin)+outputPictureFormat,image)
    i_begin+=1
    if cv2.waitKey(waitkey_time) & 0xFF==ord(quit):
        break
cap.release()
cv2.destroyAllWindows()

3.参数说明

inputVideoPath和inputVideoName分别表示所要打开视频的路径和名称。

i_begin表示保存的每帧图片是从i_begin.jpg开始命名的,后面依次递增。

outputPicturePath和outputPictureFormat分别表示保存每一帧图片的路径和名称。

imshowWindowName表示显示每一帧图片窗口的名称。

quit表示该字符被按下,视频关闭。

4.运行结果

在运行之前,我们需要在代码所在的目录下手动创建sp和sq两个文件夹,并且将要打开的视频test.avi放在sp文件夹中。之后运行程序,将会跳出窗口,显示视频内容。键盘输入q,则视频和窗口关闭。这时候会在sq文件夹中找到命名为0.jpg,1.jpg,2.jpg,…的连续帧图片。

五、连续帧的图片转化为视频

1.C++版本

#include <iostream>
#include<string.h>
#include<fstream>
#include<Windows.h>
#ifdef _WIN32
#define OPENCV
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui_c.h>
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <fstream>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2/imgproc/types_c.h>
#include <math.h>
#include <opencv2/core/core.hpp>    
#include <opencv2/ml/ml.hpp>  

using namespace std;
using namespace cv;
using namespace ml;

std::string inputPicturePath = "pp\\";
std::string inputPictureFormat = ".jpg";
int i_begin = 0;
double fps = 25.0;
std::string outputVideoPath = "qq\\";
std::string outputVideoName = "test.avi";
std::string imshowWindowName = "result";
int quit = 'q';
int fourcc = cv::VideoWriter::fourcc('M', 'P', '4', '2');
int waitkey_time = int(1000/fps);

int main()
{
	cv::Mat frame=cv::imread(inputPicturePath + to_string(i_begin) + inputPictureFormat);
	if (frame.empty())
		return -1;
	int picture_width = frame.cols;
	int picture_height = frame.rows;
	cout << "width:" << picture_width << '\n' << "height:" << picture_height;
	cv::VideoWriter video(outputVideoPath + outputVideoName, fourcc, fps, cv::Size(picture_width, picture_height));

	while (true)
	{
		cv::Mat frame = cv::imread(inputPicturePath + to_string(i_begin) + inputPictureFormat);
		if (frame.empty())
			break;
		cv::namedWindow(imshowWindowName, CV_WINDOW_NORMAL);
		cv::imshow(imshowWindowName, frame);
		i_begin++;
		video << frame;
		int q = cv::waitKey(waitkey_time);
		if (q == quit)
			break;
	}
	video.release();
	cv::destroyAllWindows();
	return 0;
}

2.Python版本

import cv2

inputPicturePath='pp/'
inputPictureFormat='.jpg'
i_begin=0
fps=25.0
outputVideoPath='qq/'
outputVideoName='test.avi'
imshowWindowName='result'
quit='q'
fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', '2')
waitkey_time = int(1000/fps)

image=cv2.imread(inputPicturePath + str(i_begin) + inputPictureFormat)
try:
    image.shape
except:
    exit()
picture_width = image.shape[1];
picture_height = image.shape[0];
size = (int(picture_width), int(picture_height))
print("width:",picture_width)
print("height:",picture_height)
out=cv2.VideoWriter(outputVideoPath+outputVideoName, fourcc, fps, size)

while(out.isOpened()):
    image=cv2.imread(inputPicturePath + str(i_begin) + inputPictureFormat)
    try:
        image.shape
    except:
        break
    
    cv2.namedWindow(imshowWindowName, cv2.WINDOW_NORMAL)
    cv2.imshow(imshowWindowName,image)
    i_begin+=1
    out.write(image)
    if cv2.waitKey(waitkey_time) & 0xFF==ord(quit):
        break
out.release()
cv2.destroyAllWindows()

3.参数说明

inputPicturePath和inputPictureFormat分别表示所要读取连续帧图片的路径和名称。

i_begin表示保存的每帧图片是从i_begin.jpg开始命名的,后面依次递增。

fps为创建的视频流的帧率。

outputVideoPath和outputVideoName分别表示保存视频的路径和名称。

imshowWindowName表示显示每一帧图片窗口的名称。

quit表示该字符被按下,停止读取连续帧图片。

fourcc表示压缩帧视频轨道的编解码器的4个字符的代码。

waitkey_time表示等待按键按下时间,也可以作为设置读取图片的时间。

4.运行结果

在运行之前,我们需要在代码所在的目录下手动创建pp和qq两个文件夹,并且将命名为0.jpg,1.jpg,2.jpg,…的连续帧图片放在pp文件夹中。之后运行程序,将会跳出窗口,显示连续帧图片内容。键盘输入q,则连续帧图片和窗口关闭。这时候会在qq文件夹中找到新生成的视频test.avi。

  • 9
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值