Camera_Net 库
Camera_Net 是一个 FLOSS 库,用于在 .NET 项目中轻松使用视频摄像头和视频输入。
- 下载已编译的示例 v1.1.2 - 170.8 KB
- 下载已编译的库 v1.1.2(托管程序集)。.NET4, .NET2, .NET35 - 340 KB
- 下载库和示例的源代码 v1.1.2 (C#) - 895.8 KB
Camera_Net 库的复杂示例。电视上的陌生人。
本文介绍了一个名为 Camera_Net
的库,用于在 .NET 中轻松处理摄像头和视频输入。该库使用 DirectShow,并包含使用示例:两个简单的示例和一个复杂的示例。
引言
什么是 DirectShow?
首先,在本文中,我们将使用 DirectShow 来渲染来自摄像头的视频流。那么,DirectShow 是什么?DirectShow 是微软公司推出的一个多媒体框架。这个框架被设计得非常强大和复杂,几乎允许你创建一个家庭级的半专业视频工作室。但是,这种巨大的复杂性使得它很难使用。你需要编写大量的代码才能仅仅将网络摄像头的视频渲染到你的应用程序窗口中。
DirectShow 的优缺点
优点
- 强大.
它可以做你需要的一切。如果不能,就编写自己的过滤器并将其用于过滤器图中。 - 操作系统的一部分.
所有 Windows 版本(XP、Vista、7、8)都开箱即用地支持它。无需安装任何东西。 - 所有厂商都支持.
几乎所有你能买到的摄像头都有驱动程序可以很好地配合 DirectShow 使用。
缺点
- 它不是跨平台的。
它基于 COM 技术,不是跨平台的。它只能在 Windows 上运行良好。它也是专有的框架,就像微软的大部分产品一样。
但是,如果你使用的是托管代码(例如 C#),那么你的应用程序很可能已经不是跨平台的了。 - 原生代码。
该框架不支持托管 API。
但是你可以使用像 DirectShowNet 库 这样的开源包装器来克服这个缺点。 - 过于复杂且底层,难以使用。
要渲染你的网络摄像头,你需要进行大量编码工作。
但是,使用像本文提供的 Camera_Net 库 这样的包装器,你可以轻松地完成很多关于摄像头的操作。
所以,是否使用 DirectShow 取决于你,因为它有优缺点。但如果你确实要用,那么这篇文章可能适合你。
DirectShow 渲染图
DirectShow 中音频/视频渲染的主要思想是构建一个过滤器图并运行它。 过滤器图 — 是一个带有块(过滤器)的图。其中一些块是视频/音频源(例如摄像头、调谐器),一些是渲染器,还有一些是能够改变或转换多媒体流的过滤器。此外,这些图过滤器还具有引脚 — 用于连接过滤器。因此,摄像头有一个或多个输出引脚,渲染器有输入引脚,大多数其他过滤器都有这两种引脚。
要渲染你的摄像头,你可以创建一个非常简单的过滤器图
源过滤器连接到简单的视频渲染器。源过滤器可用是因为操作系统找到了它,有时借助摄像头的驱动程序。渲染器是一个标准的过滤器,你可以将其视为 DirectShow 框架的一部分。没有使用额外的过滤器。
假设我们想拍摄视频流的照片并在视频输出上绘制(视频叠加)。那么图就会变得更复杂
这里的 Tee Filter 是一个标准的过滤器,用于复制多媒体流。它的一个输出流流向渲染器,另一个流向 SampleGrabber
以拍摄照片(快照)。SampleGrabber
是一个用于从视频流中获取帧的标准过滤器。在此图中,使用视频混合渲染器而不是简单的视频渲染器过滤器。视频混合渲染器是一个支持渲染输出视频叠加的标准过滤器。
如果源过滤器(摄像头、调谐器)具有不同的输出多媒体格式(媒体类型),则可能需要添加额外的中间过滤器进行实时转换。这会使过滤器图变大且更复杂。
DirectShow 可以以“智能”方式连接具有不同媒体类型的引脚,通过枚举操作系统中安装的可用中间过滤器并自行选择一个,但结果有时可能不如你预期。
过滤器图的图像是在一个名为 GraphStudioNext 的开源工具中制作的,我推荐给所有处理过滤器图的人。这是一个很棒的免费软件工具,用于构建和调试过滤器图。它是作为微软过时且有 bug 的 GraphEdit 的替代品而创建的。
作为 DirectShow 包装器的托管库
为了忽略 DirectShow 图的这些混乱,我建议使用一个托管包装器,它会隐藏所有这些底层魔术。它将允许你克服 DirectShow 的第三个缺点 — 复杂性和底层编码。
在本文中,我将描述 Camera_Net
库的用法和功能。创建这个库是因为我在数十个开源解决方案中未能找到一个能够满足我需求的库:能够轻松地将摄像头用作托管组件,能够更改摄像头分辨率,捕获帧快照,在帧上显示叠加图像。所以,这个库就应运而生了!
该库的一些功能
- 选择摄像头
- 选择分辨率
- 显示摄像头输出
- 在帧上叠加图像
- 拍摄帧快照
- 更改电视模式(PAL、NTSC 等)
- 显示摄像头的对话框窗口(来自驱动程序)
- 获取可用摄像头和分辨率列表
CameraControl
和 Camera
类是库中的主要类。Camera
类用于与摄像头交互。CameraControl
是 Camera
类的 UserControl
包装器,易于开箱即用。
此外,还有几个 public
类:Resolution
、VideoInput
、摄像头选择类等。该库使用 DirectShowLib
(许可证 LGPL 2.1 或更高版本),它是一个非常精简的 DirectX COM 接口包装器,因此使用托管代码而不是原生代码所带来的生产力损失最小。
库和示例的所有源代码都可以在 GitHub 上找到。你可以在那里提交问题、请求合并或分支。
DirectShow 仅适用于 Windows,因此该库也仅适用于 Windows。
使用 Camera_Net
使用此库最简单的方法是将其作为 Control
添加到你的应用程序中。CameraControl
类(它继承自UserControl
)负责这一点。推荐使用此方法。
该库包含 WinForms 的使用示例,特别是将组件简单实现到你的应用程序中的示例,以及展示库几乎所有功能的更复杂示例。
因此,将库项目或已编译的程序集添加到引用中,将 CameraControl
添加到你的应用程序,并添加 using
指令。
using Camera_NET;
using DirectShowLib;
获取可用设备列表
首先,你可能想获取系统中可用的摄像头和视频输入列表。
// Camera choice helper class
CameraChoice _CameraChoice = new CameraChoice();
_CameraChoice.UpdateDeviceList();
现在 _CameraChoice.Devices
包含所有可用设备(它是 List<DsDevice>
)。如果 DirectShow 未找到任何设备,列表将为空。
在示例中,你可以看到通过 ComboBoxes(带有可读的摄像头名称)进行摄像头和分辨率选择的完整代码。为了使本文简短,让我们简单地使用第一个(索引为零)。
Moniker(设备标识)
在 DirectShow 中,摄像头设备有一个唯一的标识 — Moniker(有关更多信息,请阅读 System.Runtime.InteropServices.ComTypes.IMoniker
接口)。
你可以通过 DsDevice
的 Mon
属性获取设备的 moniker。
var moniker = _CameraChoice.Devices[your_index].Mon;
获取可用分辨率列表
你可以使用 static
函数 Camera.GetResolutionList(moniker)
获取可用分辨率列表(如果摄像头驱动程序支持此功能)。
ResolutionList resolutions = Camera.GetResolutionList(moniker);
开始摄像头输出
最后,当你选择了摄像头设备和分辨率后,你可以将摄像头设置给 CameraControl
。
cameraControl.SetCamera(moniker, resolutions[your_index_of_resolution]);
或者你可以使用默认分辨率开始(通常是 VGA 模式 640x480,但不总是如此)。
cameraControl.SetCamera(moniker, null);
关闭摄像头
在更改摄像头或应用程序退出时,你可以(不一定总是需要)关闭当前摄像头。
cameraControl.CloseCamera();
这将使摄像头可供其他应用程序使用,释放 DirectShow 图和其他一些资源。
还有更多!
该库还支持更多功能。
- 拍摄视频输出的快照
SnapshotOutputImage()
或拍摄源帧的快照SnapshotSourceImage()
。 - 在视频上显示叠加图像(位图),混合器支持透明度(属性
MixerEnabled
、OverlayBitmap
、GDIAlphaValue
、GDIColorKey
等)。 - 使用带交叉开关的视频输入设备并处理交叉开关(
CrossbarAvailable
、VideoInput
)。 - 显示摄像头的对话框窗口(来自驱动程序):
DisplayPropertyPage_Device()
、DisplayPropertyPage_Crossbar()
、DisplayPropertyPage_CaptureFilter()
。 - 处理电视模式(PAL、NTSC 等):
SetTVMode()
、GetTVMode()
。 - 更改摄像头和分辨率(再次使用
SetCamera()
)。
有关更多信息,你可以查看随库提供的示例。
一个简单的示例应用程序,作为 Camera_Net 库用法的演示。
许可证
Camera_NET 库许可证
本库是自由软件;你可以根据自由软件基金会发布的 GNU Lesser General Public License 的条款重新分发和/或修改它;可以是许可证的版本 3.0,或者(由你选择)任何更高版本。本库的发布目的是希望它会有用,但没有任何保证;甚至没有适销性或特定用途适用性的隐含保证。详情请参阅 GNU Lesser General Public License。
示例许可证
虽然 Camera_Net
库受 LGPL 保护,但示例以公共领域发布。因此,你可以不受任何限制地在你的免费或专有项目中使用这些示例中的代码。
致谢
本文和 Camera_Net
库的作者是free5lot。库和示例的所有源代码都可以在 github 上找到。
本项目使用了 DirectShowLib (DirectShow.Net 库) 这个库,该库受 LGPL 2.1 或更高版本的保护。
历史
版本 1.1.2
-
为不能在窗体编辑器中使用且在序列化过程中会产生警告的属性添加了
[Browsable(false)]
和[DesignerSerializationVisibility]
特性。
- PostBuildEvent 用于发布 DLL 输出
版本 1.1.1
- 修复了从一个监视器移动到第二个监视器时的问题
- .NET2 和 .NET3.5 程序集与 .NET4 一起提供。
版本 1.1.0
一些重大修复(参见 github 日志)。对代码进行了一些清理。添加了新示例 — "VerySimple
"。
版本 1.0.0
Camera_Net
库的第一个公开开源版本。