EmguCV学习笔记 VB.Net 9.2 VideoWriter类

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

EmguCV是一个基于OpenCV的开源免费的跨平台计算机视觉库,它向C#和VB.NET开发者提供了OpenCV库的大部分功能。

教程VB.net版本请访问:EmguCV学习笔记 VB.Net 目录-CSDN博客

教程C#版本请访问:EmguCV学习笔记 C# 目录-CSDN博客

笔者的博客网址:https://blog.csdn.net/uruseibest

教程配套文件及相关说明以及如何获得pdf教程和代码,请移步:EmguCV学习笔记

学习VB.Net知识,请移步: vb.net 教程 目录_vb中如何用datagridview-CSDN博客

 学习C#知识,请移步:C# 教程 目录_c#教程目录-CSDN博客

9.2 VideoWriter类

VideoWriter类提供了将帧图像数据保存为视频文件的功能。

9.2.1 构造函数

VideoWriter类常用的1个构造函数:

Public Sub New(fileName As String, compressionCode As Integer, fps As Double, size As System.Drawing.Size, isColor As Boolean)

参数说明:

  1. fileName:保存的视频文件名。如果需要保存的视频文件已经存在,那么videowriter类将会删除原文件,并创建一个新的视频文件。
  2. codecId:视频编解码器的代码,详见9.2.2节【Fourcc方法】。
  3. fps:视频的帧率。
  4. size:视频的宽度和高度。
  5. isColor:是否保存彩色视频。

以下是VideoWriter构造函数的示例代码:

Dim vw As New VideoWriter("C:\saved-movie.mp4", codecId, 25, New Drawing.Size(640, 480), True)

9.2.2 Fourcc方法

Four cc是一个用于指定视频编解码器的4字节代码,是一个由四个ASCII字符组成的标识符。Four cc的作用是告诉计算机如何编解码视频文件并正确地显示它。

常见的编解码器格式对应Four cc如下:

编码

Four cc

编码

Four cc

编码

Four cc

MPEG-4

DIVX

MPEG-1

PTM1

MPEG-4.2

MP42

MPEG-4.3

DIV3

H263

U263

H263I

I263

H.264

AVC1

H.265

HEVC

FLV1

FLV1

编码不同,对电脑性能要求不同,生成文件大小也不同。具体需要哪种编码,要根据实际需求进行综合考虑。

VideoWriter类提供了fourcc静态方法,通过传入的4字符返回一个编解码器的代码。声明如下:

Public Shared Function Fourcc(c1 As Char, c2 As Char, c3 As Char, c4 As Char) As Integer

9.2.3 Write方法

Write方法用于将一帧图像写入视频文件中。该方法声明如下:

Public Sub Write(frame As Emgu.CV.IInputArray)

参数说明:

  1. frame:要写入视频文件的帧,类型为Mat。

write方法只能将一帧图像写入视频文件中。如果需要将多帧图像写入视频文件中,可以在write方法的调用中使用循环来实现。

【代码位置:frmChapter9_1】Button11_Click

    '写入视频文件

    Private Sub Button11_Click(sender As Object, e As EventArgs) Handles Button11.Click

        Dim vc As New VideoCapture("C:\learnEmgucv\movie1.mp4")

        If vc.IsOpened = False Then

            Exit Sub

        End If

        Dim codecId As Integer

        'Mpeg-4.2编码

        codecId = VideoWriter.Fourcc("M"c, "P"c, "4"c, "2"c)

        '宽度,同源视频文件

        Dim width As Integer = vc.Get(CapProp.FrameWidth)

        '高度,同源视频文件

        Dim height As Integer = vc.Get(CapProp.FrameHeight)

        '帧率,同源视频文件

        Dim movieFps As Double = vc.Get(CapProp.Fps)

        '使用Mpeg-4.2来编码

        Dim vw As New VideoWriter("C:\learnEmgucv\saved-movie.mp4", codecId, 50, New Drawing.Size(width, height), True)

        Dim m As Mat = New Mat()

        While True

            m = vc.QueryFrame

            If IsNothing(m) Then

                Exit While

            End If

            If m.IsEmpty Then

                Exit While

            End If

            ImageBox1.Image = m

            ImageBox1.Refresh()

            '将帧图像输出到文件

            vw.Write(m)

            Threading.Thread.Sleep(1000 \ movieFps)

        End While

        vc.Dispose()

        vw.Dispose()

        Label1.Text = "保存完毕"

End Sub

【代码位置:frmChapter9_1】Button12_Click、Button13_Click

    '是否停止录制视频标记

    Dim stopRecord As Boolean

    '开始录制摄像头视频

    Private Sub Button12_Click(sender As Object, e As EventArgs) Handles Button12.Click

        Dim vc As New VideoCapture(0)

        If vc.IsOpened = False Then

            Exit Sub

        End If

        Dim codecId As Integer

        'Mpeg-4.2编码

        codecId = VideoWriter.Fourcc("M"c, "P"c, "4"c, "2"c)

        '使用Mpeg-4.2来编码

        Dim vw As New VideoWriter("C:\learnEmgucv\saved-movie1.mp4", codecId, 25, New Drawing.Size(640, 480), True)

        Dim m As Mat = New Mat()

        stopRecord = False

        While stopRecord = False

            m = vc.QueryFrame

            If IsNothing(m) Then

                Exit While

            End If

            If m.IsEmpty Then

                Exit While

            End If

            Dim mout As New Mat

            CvInvoke.Canny(m, mout, 160, 250, 3)

            ImageBox1.Image = mout

            ImageBox1.Refresh()

            '输出到文件

            vw.Write(mout)

            '需要增加doevents,否则会出现不响应

            Application.DoEvents()

        End While

        '必须释放资源

        vc.Dispose()

        vw.Dispose()

        Label1.Text = "保存完毕"

    End Sub

    '停止录制摄像头视频

    Private Sub Button13_Click(sender As Object, e As EventArgs) Handles Button13.Click

        stopRecord = True

End Sub

事实上,在录制摄像头视频时,即使在循环中加了Application.DoEvents(),程序运行时也会出现卡顿的情况。在实际中最好是在ImageGrabbed事件中进行处理。

【代码位置:frmChapter9_1】Button14_Click、vc3_ImageGrabbed、Button15_Click

    Dim vc3 As VideoCapture

    Dim vw3 As VideoWriter

    '是否停止录制

    Dim stopRecord3 As Boolean = False

    '调用ImageGrabbed进行录制视频

    Private Sub Button14_Click(sender As Object, e As EventArgs) Handles Button14.Click

        vc3 = New VideoCapture(0)

        If vc3.IsOpened = False Then

            MessageBox.Show("打开摄像头失败")

            Exit Sub

        End If

        'stopRecord3 = False

        Dim codecId As Integer

        'Mpeg-4.2编码

        codecId = VideoWriter.Fourcc("M"c, "P"c, "4"c, "2"c)

        vw3 = New VideoWriter("C:\learnEmgucv\saved-movie2.mp4", codecId, 25, New Drawing.Size(640, 480), True)

        '添加ImageGrabbed事件

        AddHandler vc3.ImageGrabbed, AddressOf vc3_ImageGrabbed

        '启动

        vc3.Start()

    End Sub

    'ImageGrabbed事件里面进行录制视频

    Private Sub vc3_ImageGrabbed(sender As Object, e As EventArgs)

        Dim nextframe As New Mat

        If stopRecord3 = True Then

            '取消事件

            RemoveHandler vc3.ImageGrabbed, AddressOf vc3_ImageGrabbed

            '释放资源

            vc3.Dispose()

            vw3.Dispose()

            Label1.Text = "录制结束"

        Else

            '获得视频图像

            vc3.Retrieve(nextframe)

            '输出

            vw3.Write(nextframe)

            ImageBox1.Image = nextframe

            Threading.Thread.Sleep(40)

        End If

    End Sub

    Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click

        stopRecord3 = True

End Sub

【代码位置:frmChapter9_1】Button16_Click、getMask

    '模拟实现绿幕视频和其他视频合并并输出

    '1、为了简化说明,未采用在ImageGrabbed事件中进行处理

    '2、为了取得更好的效果,在实际中还需要考虑对抠图的部分进行边缘处理

    Private Sub Button16_Click(sender As Object, e As EventArgs) Handles Button16.Click

        '前景是一个绿幕视频

        Dim vc1 As New VideoCapture("c:\learnEmgucv\前景.wmv")

        If vc1.IsOpened = False Then

            MessageBox.Show("打开前景文件失败")

            Exit Sub

        End If

        '获得前景视频的帧率

        Dim fps1 As Double = vc1.Get(CapProp.Fps)

        '获得前景文件的帧数

        Dim frames1 As Integer = vc1.Get(CapProp.FrameCount)

        '背景视频

        Dim vc2 As New VideoCapture("c:\learnEmgucv\背景.mp4")

        If vc2.IsOpened = False Then

            MessageBox.Show("打开背景文件失败")

            Exit Sub

        End If

        '获得背景视频的帧率

        Dim fps2 As Double = vc2.Get(CapProp.Fps)

        '获得背景文件的帧数

        Dim frames2 As Integer = vc2.Get(CapProp.FrameCount)

        '输出编码,使用MPEG-4.3

        Dim vfourcc As Integer

        vfourcc = Emgu.CV.VideoWriter.Fourcc("D"c, "I"c, "V"c, "3"c)

        Dim vw As New VideoWriter("c:\learnEmgucv\output-movie.avi", vfourcc, 25, New Size(vc1.Width, vc1.Height), True)

        '输出帧数为两个视频帧数相比较最小的

        Dim maxframecount As Integer = IIf(frames1 > frames2, frames2, frames1)

        For i As Integer = 0 To maxframecount - 1

            Console.WriteLine("处理:" & i)

            '读取前景视频的一帧

            Dim m1 As New Mat

            vc1.Read(m1)

            Dim mmask1 As New Mat

            mmask1 = getMask(m1)

            Dim mfront As New Mat

            CvInvoke.BitwiseAnd(m1, mmask1, mfront)

            '读取背景视频的一帧

            Dim m2 As New Mat

            vc2.Read(m2)

            Dim mmask2 As New Mat

            mmask2 = Not mmask1

            Dim mback As New Mat

            CvInvoke.BitwiseAnd(m2, mmask2, mback)

            Dim mout As New Mat

            mout = mfront + mback

            vw.Write(mout)

            '代码会不定位置出现错误提示:

            'OpenCV: Failed to allocate xxxxx bytes”

            '错误的原因主要是提供的内存不足,无法加载更多数据。

            '解决方法:

            '有些网站提出需要切换到64位编译

            '但是经过测试仍然会出现上述错误

            '最好是把所有资源都释放了(如下)。经测试没有发生错误。

            mmask1.Dispose()

            mmask2.Dispose()

            mfront.Dispose()

            mback.Dispose()

            mout.Dispose()

            Threading.Thread.Sleep(40)

        Next

        vc1.Dispose()

        vc2.Dispose()

        Label1.Text = "输出视频完成"

    End Sub

    '将获得的图像根据颜色范围二值化。

    Private Function getMask(ByVal inputMat As Mat) As Mat

        Dim mhsv As New Mat

        CvInvoke.CvtColor(inputMat, mhsv, ColorConversion.Bgr2Hsv)

        '这里测试的是在这两个颜色范围之间

        Dim lower As New ScalarArray(New MCvScalar(35, 43, 46))

        Dim upper As New ScalarArray(New MCvScalar(77, 255, 255))

        '提取图像中某个颜色范围内的像素

        '颜色值在范围内,则将其设置为白色(255),否则将其设置为黑色(0

        Dim mmask As New Mat

        CvInvoke.InRange(mhsv, lower, upper, mmask)

        '根据实际需要判断是否反转颜色

        Dim mreversalmask As New Mat

        mreversalmask = Not mmask

        '以下代码输出二值图作为mask的彩色图,也就是原图去除了绿色背景

        Dim m3channel As New Mat

        CvInvoke.CvtColor(mreversalmask, m3channel, ColorConversion.Gray2Bgr)

        Return m3channel

End Function

输出结果如下图所示:

图9-4 模拟绿幕抠图生成视频

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/872993.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构与算法 | 灵神题单 | 删除链表篇】力扣3217, 82, 237

总结,删除链表节点问题使用到列表,哈希表,递归比较容易超时,我觉得使用计数排序比较稳,处理起来也不是很难。 1. 力扣3217:从链表中移除在数组中的节点 1.1 题目: 给你一个整数数组 nums 和一…

Azure AI Search 中的二进制量化:优化存储和加快搜索速度

随着组织继续利用生成式 AI 的强大功能来构建检索增强生成 (RAG) 应用程序和代理,对高效、高性能和可扩展解决方案的需求从未如此强烈。 今天,我们很高兴推出二进制量化,这项新功能可将向量大小减少高达 96%,同时将搜索延迟减少高…

集合及映射

1、集合类图 1)ArrayList与LinkedList 区别 LinkedList 实现了双向队列的接口,对于数据的插入速度较快,只需要修改前后的指向即可;ArrayList对于特定位置插入数据,需要移动特定位置后面的数据,有额外开销 …

Spring Boot-自定义banner

在 Spring Boot 应用中,你可以自定义启动时显示的 banner。这些 banner 可以包括图形、文字或者其他形式的标识。如图所示: 1. 使用 banner.txt 文件 默认情况下,Spring Boot 使用项目的 banner.txt 文件中的内容作为启动时的 banner。你可以…

Verilog语法+:和-:有什么用?

Verilog语法:和-:主要用于位选择,可以让代码更简洁。 一、位选择基础 在Verilog中,位选择可以通过直接索引来实现,例如: reg [7:0] data; wire select_a; wire [2:0] select_b; assign select_a data[3]; assign select_b …

【Hot100】LeetCode—739. 每日温度

目录 1- 思路单调栈 2- 实现⭐739. 每日温度——题解思路 3- ACM 实现 原题链接&#xff1a;739. 每日温度 1- 思路 单调栈 寻找当前位置的下一个比他大的元素的位置利用 Stack 栈维护一个单调栈 当前元素 < 栈顶元素&#xff0c;直接压栈否则 利用 while 循环判断 2- 实…

备忘录怎么隐藏起来 适合记录秘密的备忘录推荐

备忘录作为我们日常生活中常用的记录工具&#xff0c;经常被用来记录重要资料或工作事项。然而&#xff0c;当我们需要在备忘录中记录一些涉及个人隐私的内容时&#xff0c;如何确保这些信息不被他人轻易窥视&#xff0c;保护内容的安全就显得尤为重要。 想象一下&#xff0c;…

【数学建模国赛思路预约】2024全国大学生数学建模竞赛助攻思路、代码、论文

2024年全国大学生数学建模大赛马上就要开始了&#xff0c;大家有没有准备好呢&#xff0c;今年将会和之前一样&#xff0c;将会在比赛赛中时期为大家提供比赛各题的相关解题思路、可运行代码参考以及成品论文。 一、分享计划表如下所示 1、 赛中分享内容包括&#xff08;2023国…

【LeetCode】06.Z字形变换

题目要求 解题思路 首先映入我们脑海的就是暴力。这一方法可行&#xff0c;但是时间复杂度空间复杂度很高&#xff0c;因此我们使用找规律的方法。这样的话我们可以模拟插入下标&#xff0c;这样的话很容易发现首行和末行插入的位置刚好是d2*n-2&#xff0c;而中间行的两个位置…

视频编码与传输 学习笔记 1 一些视频压缩算法的介绍

大概是这么个结构&#xff1a; 说白了&#xff0c;就是视频太大&#xff0c;不压缩不行&#xff0c;因此我们会用压缩比非常夸张但对于视频来说效果很好的压缩方法先对视频压缩&#xff08;source coding&#xff09;然后把压缩后的视频发出去&#xff0c;要看的时候再解压。 就…

3. GIS后端工程师岗位职责、技术要求和常见面试题

本系列文章目录&#xff1a; 1. GIS开发工程师岗位职责、技术要求和常见面试题 2. GIS数据工程师岗位职责、技术要求和常见面试题 3. GIS后端工程师岗位职责、技术要求和常见面试题 4. GIS前端工程师岗位职责、技术要求和常见面试题 5. GIS工程师岗位职责、技术要求和常见面试…

交换机自动化备份配置(H3C_无人值守)

介绍&#xff1a; 在日常运维过程中&#xff0c;需要定时备份设备的配置&#xff0c;在设备数量过于庞大的情况下&#xff0c;对我们的运维工作会造成极大地不便&#xff0c;通过python自动化能够完美解决人工手动保存设备配置的问题。而且自动化运维在未来也一定是大势所趋&a…

STM32G474之TIM1输出PWM信号支持互补输出,死区时间和刹车

STM32G474之TIM1输出PWM信号&#xff0c;互补输出&#xff0c;支持死区时间和刹车。PWM第1通道输出引脚配置&#xff1a;TIM1_CH1映射到PA8,TIM1_CH1N映射到PA7&#xff0c;TIM1_BKIN映射到PA6&#xff0c;用作刹车输入信号。当刹车时&#xff0c;停止PWM波形输出。在使用“比较…

JAVAEE初阶第六节——网络编程套接字

系列文章目录 JAVAEE初阶第六节——网络编程套接字 文章目录 系列文章目录JAVAEE初阶第六节——网络编程套接字 一. 网络编程基础1. 为什么需要网络编程2. 什么是网络编程3.网络编程中的基本概念 3.1 发送端和接收端 3.2 请求和响应 3.3 客户端和服务端 4. 常见的客户端服务…

【2024数模国赛赛题思路公开】国赛C题第三套思路丨无偿自提

C题参考思路 C题是一道优化问题&#xff0c;目的是根据题目所给的种植限制条件以及附件数据建立目标条件优化模型&#xff0c;优化种植策略&#xff0c;有利于方便田间管理&#xff0c;提高生产效益&#xff0c;减少各种不确定因素可能造成的种植风险。整个题目最重要的问题在…

英语每日一段 195

Promising economic indicators won’t instantly reverse the lingering impact of hard times for millions of families, workplace culture expert Jessica Kriegel said. “Perception and reality are sometimes aligned and sometimes not,” Kriegel told Newsweek. “…

C语言中的预处理指令中的其中一对——#ifdef和#ifndef

目录 开头1.什么是#ifdef和#ifndef?2.#ifdef和#ifndef的实际应用判断ABCD这个宏是否被定义过判断HELLO这个宏是否没被定义过防止头文件重复定义 下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。今天&#xff0c;我们要学一下关于C语言中的预处理指令中的其中一对…

剖析Cookie的工作原理及其安全风险

Cookie的工作原理主要涉及到HTTP协议中的状态管理。HTTP协议本身是无状态的&#xff0c;这意味着每次请求都是独立的&#xff0c;服务器不会保留之前的请求信息。为了在无状态的HTTP协议上实现有状态的会话&#xff0c;引入了Cookie机制。 1. Cookie定义 Cookie&#xff0c;也…

多线程的实现和成员方法

所属专栏&#xff1a;Java学习 1. 多线程的概念 线程&#xff1a;线程是操作系统能够进行运算调度的最小单位&#xff0c;它被包含在进程之中&#xff0c;是进程的实际运作单位 下面这些每一个能够运行的软件就是一个进程 进程在系统中是通过PCB这样的结构体来描述&am…

Datawhle X 李宏毅苹果书AI夏令营深度学习笔记之——卷积神经网络的前世今生

一、卷积神经网络简介 卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;是一种深度学习模型&#xff0c;尤其擅长处理图像和视频等高维度的数据。CNN 通过模仿人类视觉系统的工作方式&#xff0c;自动学习数据中的空间层次结构&#xff0c;使得它在计算…