Emgucv视频操作--进阶1
时间:2022-07-23
本文章向大家介绍Emgucv视频操作--进阶1,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
实现功能:
- 播放视频
- 提取每一帧图片并保存
- 显示视频播放的时间 videowrite 视频保存的方法还未调试成功,等待后续再继续研究!
//----------------------------------------------------------------------------
// Copyright (C) 2004-2019 by EMGU Corporation. All rights reserved.
//----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.Util;
using System.Threading;
namespace CameraCapture
{
public partial class CameraCapture : Form
{
private VideoCapture _capture = null;
private bool _captureInProgress;
private Mat _frame, _frame1;
private Mat _grayFrame;
private Mat _smallGrayFrame;
private Mat _smoothedGrayFrame;
private Mat _cannyFrame;
private double FrameRate;
private int cam,count;
Bitmap bmp;
//VideoWriter _Wvideo;
//private Image<Bgr, byte> frame = new Image<Bgr, byte>("你好.jpg");
//参考链接 https://blog.csdn.net/cuoban/article/details/50555953
public CameraCapture()
{
InitializeComponent();
Control.CheckForIllegalCrossThreadCalls = false;//加入这句话,不过治标不治本
//使用显卡处理图像数据效率会很多,如果你的设备支持,最好打开,使用CvInvoke.HaveOpenCLCompatibleGpuDevice能返回是否支持.
// 配置CvInvoke.UseOpenCL能让OpenCV 启用或者停用 GPU运算
//CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;
CvInvoke.UseOpenCL = false;
count = 0;
try
{
//构造一个摄像头实例,如果调用本地摄像机则括号里面为空
_capture = new VideoCapture(@"C:UsersAdministratorDesktopvideovtest.avi");
_capture.ImageGrabbed += ProcessFrame;//图像捕捉事件
double TotalFrames = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
_capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameHeight, 96);
_capture.SetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameWidth, 128);//FrameWidth=3视频流的帧宽度(只对摄像头有效)
// FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FPS);
FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);//帧率
// MessageBox.Show(FrameRate.ToString());
cam = 0;
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
_frame = new Mat();
_frame1 = new Mat();
_grayFrame = new Mat();
_smallGrayFrame = new Mat();
_smoothedGrayFrame = new Mat();
_cannyFrame = new Mat();
}
private void ProcessFrame(object sender, EventArgs arg)
{
/* if (_capture != null && _capture.Ptr != IntPtr.Zero)
// if (_capture != null)
{
_capture.Retrieve(_frame, 0); //_capture.RetrieveBgrFrame(); 老版本写法 得到捕捉到的帧数据。
// _frame1 = _capture.QueryFrame();
// pictureBox1.Image = _frame1.ToBitmap();
CvInvoke.CvtColor(_frame, _grayFrame, ColorConversion.Bgr2Gray);
CvInvoke.PyrDown(_grayFrame, _smallGrayFrame);
//进行高斯向下采样,执行高斯金字塔分解步骤向下采样。固定原图像,
//删除指定行和列(可以全为奇数行和列,或者偶数行和列...),从而减小图像的宽度和高度。
CvInvoke.PyrUp(_smallGrayFrame, _smoothedGrayFrame);
//执行高斯金字塔分解向上采样,首先透过注入固定行和列0像素值,在通过插值算法,对插入行列进行插值,这样用于放大原图像的四倍。
//参数解析:IInputArraysrc:输入图像,即原图像。IOutputArraydst:输出图像,采样后得到的图像。
CvInvoke.Canny(_smoothedGrayFrame, _cannyFrame, 100, 60);
//多级边缘检测算法
captureImageBox.Image = _frame;
grayscaleImageBox.Image = _grayFrame;
smoothedGrayscaleImageBox.Image = _smoothedGrayFrame;
cannyImageBox.Image = _cannyFrame;*/
try
{
Double Framesno = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosFrames);
_capture.Retrieve(_frame, 0);
if (_frame != null)
{
//pictureBox1.Image = _frame.Bitmap;
captureImageBox.Image = _frame;
Thread.Sleep((int)(1000.0 / FrameRate));
//保存图片
bmp = new Bitmap(_frame.Bitmap);
bmp.Save(@"D:image"+count+".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Dispose();
count++;
// _Wvideo = new VideoWriter(@"D:image1.avi", -1,10,new Size(_frame.Cols, _frame.Rows),true);
if (cam == 0)
{
int Video_seek = (int)(Framesno);
double time_index = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosMsec);
label5.Text = "Time: " + TimeSpan.FromMilliseconds(time_index).ToString().Substring(0, 8);
// double framenumber = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_POS_FRAMES);
// Frame_lbl.Text = "Frame: " + framenumber.ToString();
}
if (cam == 1)
{
//Frame_lbl.Text = "Frame: " + (webcam_frm_cnt++).ToString();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
private void captureButtonClick(object sender, EventArgs e)
{
if (_capture != null)
{
if (_captureInProgress)
{ //stop the capture
captureButton.Text = "Start Capture";
_capture.Pause();
}
else
{
//start the capture
captureButton.Text = "Stop";
_capture.Start();
}
_captureInProgress = !_captureInProgress;
}
}
//Dispose意为释放,释放组件所占用的内存。
//C#特性,为提高运行效率,自动会释放已使用过且不再需要使用的组件来减少程序的CPU使用率。
//默认会在程序运行一段时间后自动加载该Dispose方法,或者可以显式的自行调用此方法。
private void ReleaseData()
{
if (_capture != null)
_capture.Dispose();
}
private void FlipHorizontalButtonClick(object sender, EventArgs e)
{
// 得到和设置Capture类是否进行水平翻转。
if (_capture != null) _capture.FlipHorizontal = !_capture.FlipHorizontal;
}
private void FlipVerticalButtonClick(object sender, EventArgs e)
{
if (_capture != null) _capture.FlipVertical = !_capture.FlipVertical;
}
}
}
要显示视频播放的时间可以以下两种方式:
- 初始化代码中加: Control.CheckForIllegalCrossThreadCalls = false;//加入这句话,不过治标不治本 视频播放还可以用
- 使用委托:SetText("Time: " + TimeSpan.FromMilliseconds(time_index).ToString().Substring(0, 8));
- private delegate void SetTextDelegate(string value); private void SetText(string value) { if (this.InvokeRequired) { SetTextDelegate d = new SetTextDelegate(SetText); object arg = (object)value;//要传入的参数值 this.Invoke(d, arg);//这里参数不对。 } else { this.label5.Text = value; } }
QueryFrame() 去实现
//----------------------------------------------------------------------------
// Copyright (C) 2004-2019 by EMGU Corporation. All rights reserved.
//----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.Util;
using System.Threading;
namespace WindowsFormsApplication40
{
public partial class Form1 : Form
{
private VideoCapture _capture = null;
private Mat _frame;
private double FrameRate;
//private Image<Bgr, byte> frame = new Image<Bgr, byte>("你好.jpg");
//参考链接 https://blog.csdn.net/cuoban/article/details/50555953
public Form1()
{
InitializeComponent();
//使用显卡处理图像数据效率会很多,如果你的设备支持,最好打开,使用CvInvoke.HaveOpenCLCompatibleGpuDevice能返回是否支持.
// 配置CvInvoke.UseOpenCL能让OpenCV 启用或者停用 GPU运算
//CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;
CvInvoke.UseOpenCL = false;
try
{
Application.Idle += Application_Idle;
//构造一个摄像头实例,如果调用本地摄像机则括号里面为空
//Application.Idle += new EventHandler(Application_Idle);//也可以
_capture = new VideoCapture(@"C:UsersAdministratorDesktopvideovtest.avi");
double TotalFrames = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);//帧率
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
private void Application_Idle(object sender, EventArgs e)
{
try
{
_frame = _capture.QueryFrame();
if (_frame != null)
{
System.Threading.Thread.Sleep((int)(1000.0 / FrameRate - 5));
pictureBox1.Image = _frame.Bitmap;
GC.Collect();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
//Dispose意为释放,释放组件所占用的内存。
//C#特性,为提高运行效率,自动会释放已使用过且不再需要使用的组件来减少程序的CPU使用率。
//默认会在程序运行一段时间后自动加载该Dispose方法,或者可以显式的自行调用此方法。
private void ReleaseData()
{
if (_capture != null)
_capture.Dispose();
}
}
}
项目拓展:
点击按钮选择需要播放的视频进行播放
//----------------------------------------------------------------------------
// Copyright (C) 2004-2019 by EMGU Corporation. All rights reserved.
//----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.Util;
using System.Threading;
namespace WindowsFormsApplication40
{
public partial class Form1 : Form
{
private VideoCapture _capture = null;
private Mat _frame;
private double FrameRate;
//private Image<Bgr, byte> frame = new Image<Bgr, byte>("你好.jpg");
//参考链接 https://blog.csdn.net/cuoban/article/details/50555953
public Form1()
{
InitializeComponent();
//使用显卡处理图像数据效率会很多,如果你的设备支持,最好打开,使用CvInvoke.HaveOpenCLCompatibleGpuDevice能返回是否支持.
// 配置CvInvoke.UseOpenCL能让OpenCV 启用或者停用 GPU运算
//CvInvoke.UseOpenCL = CvInvoke.HaveOpenCLCompatibleGpuDevice;
CvInvoke.UseOpenCL = false;
try
{
// Application.Idle += Application_Idle;
//Application.Idle += new EventHandler(Application_Idle);
//构造一个摄像头实例,如果调用本地摄像机则括号里面为空
// _capture = new VideoCapture(@"C:UsersAdministratorDesktopvideovtest.avi");
// double TotalFrames = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
//FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);//帧率
}
catch (NullReferenceException excpt)
{
MessageBox.Show(excpt.Message);
}
}
private void Application_Idle(object sender, EventArgs e)
{
try
{
_frame = _capture.QueryFrame();
if (_frame != null)
{
System.Threading.Thread.Sleep((int)(1000.0 / FrameRate - 5));
pictureBox1.Image = _frame.Bitmap;
double time_index = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.PosMsec);
label1.Text = "Time: " + TimeSpan.FromMilliseconds(time_index).ToString().Substring(0, 8);
GC.Collect();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
//Dispose意为释放,释放组件所占用的内存。
//C#特性,为提高运行效率,自动会释放已使用过且不再需要使用的组件来减少程序的CPU使用率。
//默认会在程序运行一段时间后自动加载该Dispose方法,或者可以显式的自行调用此方法。
private void ReleaseData()
{
if (_capture != null)
_capture.Dispose();
}
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog op = new OpenFileDialog();
if(op.ShowDialog() == DialogResult.OK)
{
try
{
_capture = new VideoCapture(op.FileName);
double TotalFrames = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.FrameCount);
FrameRate = _capture.GetCaptureProperty(Emgu.CV.CvEnum.CapProp.Fps);//帧率
Application.Idle += new EventHandler(Application_Idle);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
}
}
}
- 使用SQL来分析数据库参数(二)(r10笔记第82天)
- Golang不定参数
- [go语言]利用缓冲信道来实现网游帐号验证消息的分发和等待
- 转--Golang语言版 ssh口令破解工具
- cubieboard(树莓派)安装Ubuntu+Apache+PHP+Mysql
- Oracle 12c里的几点补充(一)(r11笔记第7天)
- Oracle备库的PDB无法连接的问题(r11笔记第6天)
- Golang语言社区--模板的使用
- Golang语言写Web 应用程序
- 强制wordpress后台HTTPS
- Golang语言 Cookie的使用
- Golang 语言调用动态库实现OpenGL及windows的API编程
- MySQL中的Online DDL(第一篇)(r11笔记第3天)
- 转--quick-cocos做客户端,golang做服务端,实现HTTP通信
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- CentOS 7.2搭建VNC远程桌面服务的方法
- Ubuntu挂载3T硬盘或大于2T磁盘的方法
- linux chroot命令详解
- Linux中如何查询运行文件的全路径的方法
- 基于可变自动编码器(VAE)的生成建模,理解可变自动编码器背后的原理
- Centos7上网及添加静态IP方法介绍
- 解决yum安装报错Protected multilib versions的问题
- Linux与Windows编码不一致的解决方案
- Linux运维之如何使用ss命令代替netstat
- 对Linux终端使用socks5代理的方法详解
- linux安装xmind的方法步骤
- 对linux下软件(库)的更新命令详解
- Linux环境下Apache服务器配置二级域名的方法详解
- Linux环境下Apache开启https服务的方法详解
- 使用GANs生成时间序列数据:DoppelGANger论文详解