摄像头录像与播放
视频讲解如下:
当前系列所有demo下载地址:
https://github.com/GaoRenBao/OpenCv4-Demo
不同编程语言对应的OpenCv版本以及开发环境信息如下:
语言 | OpenCv版本 | IDE |
C# | OpenCvSharp4.4.8.0.20230708 | Visual Studio 2022 |
C++ | OpenCv-4.5.5-vc14_vc15 | Visual Studio 2022 |
Python | OpenCv-Python (4.6.0.66) | PyCharm Community Edition 2022.1.3 |
这里给大大家演示OpenCv环境下是如何调用摄像头的。
实现的主要功能包括:
1、摄像头的调用
2、摄像头图像实时显示
3、通过摄像头进行录像
4、读取录像文件
C#版本代码如下:
C#版本需要需要安装“OpenCvSharp4”、“OpenCvSharp4.runtime.win”两个库才行。不然会报错。
如果需要使用“ BitmapConverter.ToBitmap”操作,则需要追加安装“OpenCvSharp4.Extensions”库。
效果展示如下:

using OpenCvSharp;
using OpenCvSharp.Extensions;
using System;
using System.Windows.Forms;
namespace WindowsFormsApp
{
public partial class Form1 : Form
{
/// <summary>
/// 视频操作
/// </summary>
public VideoCapture Cap = new VideoCapture();
/// <summary>
/// 录像
/// </summary>
public VideoWriter myavi;
/// <summary>
/// 录像开关
/// </summary>
public bool video = false;
public Form1()
{
InitializeComponent();
}
// 打开摄像头
private void button1_Click(object sender, EventArgs e)
{
// 打开ID为0的摄像头
Cap.Open(0);
// 判断摄像头是否成功打开
if (!Cap.IsOpened())
{
MessageBox.Show("摄像头打开失败.");
return;
}
/* opencv3 */
//Cap.Set(CaptureProperty.FrameWidth, 640); // 设置采集的图像宽度:640
//Cap.Set(CaptureProperty.FrameHeight, 480); // 设置采集的图像高度:480
//Cap.Set(CaptureProperty.Brightness, 1); // 亮度
//Cap.Set(CaptureProperty.Contrast, 0); // 对比度
//Cap.Set(CaptureProperty.Saturation, 100); // 饱和度
//Cap.Set(CaptureProperty.Hue, 150); // 色调
//Cap.Set(CaptureProperty.Exposure, -1); // 曝光
/* opencv4 */
Cap.Set(VideoCaptureProperties.FrameWidth, 640); // 设置采集的图像宽度:640
Cap.Set(VideoCaptureProperties.FrameHeight, 480); // 设置采集的图像高度:480
//Cap.Set(VideoCaptureProperties.Brightness, 1); // 亮度
//Cap.Set(VideoCaptureProperties.Contrast, 0); // 对比度
//Cap.Set(VideoCaptureProperties.Saturation, 100); // 饱和度
//Cap.Set(VideoCaptureProperties.Hue, 150); // 色调
//Cap.Set(VideoCaptureProperties.Exposure, -1); // 曝光
Mat Img = new Mat();
var window = new Window("capture");
// 录像控制
int end = 0;
// 视频显示
while (end < 2)
{
if (Cap.Read(Img))
{
if(video)
{
// 用户点击了开始录像
end = 1;
// 录像,本地存储
myavi.Write(Img);
}
else if(end == 1)
{
// 用户点击了结束录像
end = 2;
// 释放资源
myavi.Release();
}
// 在Window窗口中播放视频(方法1)
window.ShowImage(Img);
// 在Window窗口中播放视频(方法2)
//Cv2.ImShow("avi", Img);
// 在pictureBox1中显示效果图
pictureBox1.Image = BitmapConverter.ToBitmap(Img);
Cv2.WaitKey(10);
}
}
}
// 开始录像
private void button2_Click(object sender, EventArgs e)
{
// 定义录像的数据类, true 表示保存的是彩色图像
myavi = new VideoWriter("a.avi", FourCC.MJPG, 25, new OpenCvSharp.Size() { Width = 640, Height = 480 }, true);
video = true;
}
// 停止录像
private void button3_Click(object sender, EventArgs e)
{
video = false;
}
// 播放录像
private void button4_Click(object sender, EventArgs e)
{
var capture = new VideoCapture(@"a.avi");
// 计算帧率
int sleepTime = (int)Math.Round(1000 / capture.Fps);
using (var window = new Window("capture"))
{
// 声明实例 Mat类
Mat image = new Mat();
// 进入读取视频每镇的循环
while (true)
{
capture.Read(image);
//判断是否还有没有视频图像
if (image.Empty())
break;
// 在Window窗口中播放视频(方法1)
window.ShowImage(image);
// 在Window窗口中播放视频(方法2)
//Cv2.ImShow("avi", image);
// 在pictureBox1中显示效果图
pictureBox1.Image = BitmapConverter.ToBitmap(image);
Cv2.WaitKey(sleepTime);
}
}
}
}
}
C++版本代码如下:
#include <iostream>
#include <opencv2\opencv.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <fstream>
#include <string>
#include <vector>
using namespace cv;
using namespace std;
// demo1 摄像头图像实时显示
void demo1()
{
VideoCapture cap;
cap.open(0);
if (!cap.isOpened())
{
cout << "Error0" << endl;
while (true);
return;
}
// 尺寸为640*480
cap.set(CAP_PROP_FRAME_WIDTH, 640); // 宽度
cap.set(CAP_PROP_FRAME_HEIGHT, 480); // 高度
//cap.set(CAP_PROP_BRIGHTNESS, 1); // 亮度
//cap.set(CAP_PROP_CONTRAST, 0); // 对比度
//cap.set(CAP_PROP_SATURATION, 100); // 饱和度
//cap.set(CAP_PROP_HUE, 0); // 色调
//cap.set(CAP_PROP_EXPOSURE, 0); // 曝光
// 读取设置的参数
cout << "摄像头设置,宽度:" << cap.get(CAP_PROP_FRAME_WIDTH) << endl;
cout << "摄像头设置,高度:" << cap.get(CAP_PROP_FRAME_WIDTH) << endl;
// 摄像头实时显示
while (1)
{
Mat srcImage;
cap >> srcImage;
if (!srcImage.empty())
{
// 左右翻转, 使用笔记本电脑摄像头才有用。
flip(srcImage, srcImage, 1);
imshow("图像", srcImage);
waitKey(1);
}
}
}
// demo2 录像
void demo2()
{
VideoCapture cap;
cap.open(0);
if (!cap.isOpened())
{
cout << "Error0" << endl;
while (true);
return;
}
// 尺寸为640*480
cap.set(CAP_PROP_FRAME_WIDTH, 640); // 宽度
cap.set(CAP_PROP_FRAME_HEIGHT, 480); // 高度
// 定义编解码器并创建VideoWriter对象,可以是“MJPG”或者“XVID”
// opencv3:CV_FOURCC('M', 'J', 'P', 'G')
// opencv4:VideoWriter:: fourcc('M', 'J', 'P', 'G')
int fourcc = VideoWriter::fourcc('X', 'V', 'I', 'D');
VideoWriter writer("a.avi", fourcc, 25.0, Size(640, 480));
while (1)
{
Mat srcImage;
cap >> srcImage;
if (!srcImage.empty())
{
writer << srcImage;
imshow("录像", srcImage);
if (waitKey(10) == 27) // ESC按钮
{
cap.release();
writer.release();
destroyAllWindows();
return;
}
}
}
}
// demo3 播放录像
void demo3()
{
VideoCapture cap("a.avi");
// 帧率
int fps = cap.get(CAP_PROP_FPS);
cout << "Frames per second using video.get(cv2.CAP_PROP_FPS) : " << fps << endl;
// 总共有多少帧
int num_frames = cap.get(CAP_PROP_FRAME_COUNT);
cout << "共有" << num_frames << "帧" << endl;
int frame_height = cap.get(CAP_PROP_FRAME_HEIGHT);
int frame_width = cap.get(CAP_PROP_FRAME_WIDTH);
cout << "高:" << frame_height << ",宽:" << frame_width << endl;
int FRAME_NOW = cap.get(CAP_PROP_POS_FRAMES); // 第0帧
printf("当前帧数%d", FRAME_NOW); // 当前帧数 0.0
// 读取指定帧, 对视频文件才有效,对摄像头无效??
int frame_no = 10;
cap.set(1, frame_no); // Where frame_no is the frame you want
Mat frame;
cap >> frame; //读取当前帧
imshow("frame_no", frame);
FRAME_NOW = cap.get(CAP_PROP_POS_FRAMES);
printf("当前帧数%d\r\n", FRAME_NOW); // 当前帧数
while (1)
{
cap >> frame; //读取当前帧
//若视频播放完成,退出循环
if (frame.empty())
{
waitKey(0);
cap.release();
destroyAllWindows();
break;
}
FRAME_NOW = cap.get(CAP_PROP_POS_FRAMES); // 当前帧数
printf("当前帧数%d\r\n", FRAME_NOW);
imshow("读取视频", frame); //显示当前帧
waitKey(fps);
}
}
// 主函数
void main()
{
// demo1();
//demo2();
demo3();
}
Python版本代码如下:
Python的效果其实和前面的都差不多,这里就不放演示效果了。
注意:如果python程序无法启动摄像头,可以尝试使用下面方法
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
完整测试代码如下:
import cv2
#####################[demo1 摄像头图像实时显示]#####################
def demo1():
# 打开摄像头
# 一般的笔本电脑有内置摄像头。所以参数就是 0。你可以设置成1或者其他的来择别的摄像头
Cap = cv2.VideoCapture(0)
# 判断视频是否打开
if (Cap.isOpened() == False):
print('Open Camera Error.')
else:
'''
你可以使用函数 cap.get(propId) 来获得 的一些参数信息。
propId 可以是 0 到 18 之 的任何整数。
其中的一些值可以使用 cap.set(propId,value) 来修改value就是你想置成的新值。
例如 我可以使用 cap.get(3) cv2.CAP_PROP_FRAME_WIDTH和 cap.get(4) cv2.CAP_PROP_FRAME_HEIGHT来查看每一帧的宽和高。
默认情况下得到的值是 640X480。但是我可以使用 ret=cap.set(3,320) 和 ret=cap.set(4,240) 来把宽和高改成 320X240。
'''
# ret=cap.set(3,320)
# ret=cap.set(4,240)
# ret = cap.set(cv2.CAP_PROP_FRAME_WIDTH, 480)#避免计算量过大
# ret = cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 270)#
Cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 设置图像宽
Cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 设置图像高
Cap.set(cv2.CAP_PROP_EXPOSURE, -3) # 设置曝光值
# 读取设置的参数
size = (int(Cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(Cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
baog = int(Cap.get(cv2.CAP_PROP_EXPOSURE))
# 输出参数
print('摄像头设置,尺寸:' + str(size))
print('摄像头设置,曝光:' + str(baog))
# 读取图像
# while (True):
while Cap.isOpened(): # 检查是否成功初始化,否则就 使用函数 cap.open()
# Capture frame-by-frame
ret, frame = Cap.read() # ret 返回一个布尔值 True/False
# print('frame shape:',frame.shape)#(720, 1280, 3)
frame = cv2.flip(frame, flipCode=1) # 左右翻转,使用笔记本电脑摄像头才有用。
# flipCode:翻转方向:1:水平翻转;0:垂直翻转;-1:水平垂直翻转
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame', gray)
cv2.setWindowTitle('frame', 'COLOR_BGR2GRAY')
# Property=cv2.getWindowProperty('frame',0)#无用
# if cv2.waitKey(1) & 0xFF == ord('q'):#不行
# break
key = cv2.waitKey(delay=10)
if key == ord("q"):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
#############################[demo2 录像]######################################
def demo2():
# 打开摄像头
Cap = cv2.VideoCapture(0)
# 判断视频是否打开
if (Cap.isOpened() == False):
print('Open Camera Error.')
else:
Cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) # 设置图像宽
Cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) # 设置图像高
Cap.set(cv2.CAP_PROP_EXPOSURE, -3) # 设置曝光值
# 读取设置的参数
size = (int(Cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(Cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
baog = int(Cap.get(cv2.CAP_PROP_EXPOSURE))
# 输出参数
print('摄像头设置,尺寸:' + str(size))
print('摄像头设置,曝光:' + str(baog))
# 设置存储的录像文件格式
# 定义编解码器并创建VideoWriter对象,可以是“MJPG”或者“XVID”
fourcc = cv2.VideoWriter_fourcc(*'XVID')
# Error: 'module' object has no attribute 'VideoWriter_fourcc'
# fourcc=cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')
# jpeg,h263,'m', 'p', '4', 'v'
myavi = cv2.VideoWriter("a.avi", fourcc, 25.0, (640, 480), True)
while (Cap.isOpened()):
ret, frame = Cap.read()
if ret == True:
cv2.imshow('frame', frame)
myavi.write(frame)
if cv2.waitKey(10) & 0xFF == ord('q'):
break
else:
break
Cap.release()
myavi.release()
cv2.destroyAllWindows()
############################[播放录像]####################################
def demo3():
cap = cv2.VideoCapture('a.avi')
# cap = cv2.VideoCapture('output.avi')
# cap = cv2.VideoCapture('Minions_banana.mp4')
# 帧率
fps = cap.get(cv2.CAP_PROP_FPS) # 25.0
print("Frames per second using video.get(cv2.CAP_PROP_FPS) : {0}".format(fps))
# 总共有多少帧
num_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
print('共有', num_frames, '帧')
#
frame_height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
frame_width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
print('高:', frame_height, '宽:', frame_width)
FRAME_NOW = cap.get(cv2.CAP_PROP_POS_FRAMES) # 第0帧
print('当前帧数', FRAME_NOW) # 当前帧数 0.0
# 读取指定帧,对视频文件才有效,对摄像头无效??
frame_no = 10
cap.set(1, frame_no) # Where frame_no is the frame you want
ret, frame = cap.read() # Read the frame
cv2.imshow('frame_no' + str(frame_no), frame)
FRAME_NOW = cap.get(cv2.CAP_PROP_POS_FRAMES)
print('当前帧数', FRAME_NOW) # 当前帧数 122.0
while cap.isOpened():
# 读帧
ret, frame = cap.read()
if ret == False:
break
FRAME_NOW = cap.get(cv2.CAP_PROP_POS_FRAMES) # 当前帧数
print('当前帧数', FRAME_NOW)
cv2.imshow('frame', frame)
key = cv2.waitKey(int(fps))
if key == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
# 选择当前运行的demo
if __name__ == '__main__':
demo1()
# demo2()
# demo3()