本文简略地介绍一下如果使用AForge来实现前置/后置摄像头的预览功能。

要使用AForge,就需要添加AForge NuGet相关包的引用,这些包依赖的其他包会自动安装。

  • AForge.Controls
  • AForge.Video.DirectShow

接下来需要添加另外两个引用,主要是为了使用VideoSourcePlayer Windows Forms 控件。

  • System.Windows.Forms
  • WindowsFormsIntergration

UI界面比较简单,Xaml code 如下:

<Window x:Class="WebcamPreview.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:AForge.Controls;assembly=AForge.Controls"
mc:Ignorable="d"
Title="Webcam" Height="240" Width="640" MinHeight="240" MinWidth="640" ResizeMode="CanMinimize">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<WindowsFormsHost Background="Transparent">
<controls:VideoSourcePlayer x:Name="VideoSourcePlayer1" />
</WindowsFormsHost>
<WindowsFormsHost Background="Transparent" Grid.Column="1" >
<controls:VideoSourcePlayer x:Name="VideoSourcePlayer2" />
</WindowsFormsHost>
</Grid>
</Window>

定义一个描述video device的类。

    /// <summary>
/// Represents class that contains media information for video device source.
/// </summary>
public sealed class MediaInformation
{
/// <summary>
/// Gets or sets the display name of the video device source.
/// </summary>
public string DisplayName
{
get;
set;
} /// <summary>
/// Gets or sets the Moniker string of the video device source.
/// </summary>
public string MonikerString
{
get;
set;
}
}

实现一个WebcamDevice类,主要是用来初始化前置/后置摄像头的。

using AForge.Controls;
using AForge.Video.DirectShow;
using System;
using System.Collections.Generic;
using System.Linq; namespace WebcamPreview
{
public class WebcamDevice
{
// <summary>
/// Instance of video capture device.
/// </summary>
private VideoCaptureDevice videoCaptureDevice;
private VideoSourcePlayer videoPlayer;
private string deviceMoniker; public WebcamDevice(VideoSourcePlayer player, string deviceMoniker)
{
this.videoPlayer = player;
this.deviceMoniker = deviceMoniker;
} public void Init()
{
try
{
this.videoCaptureDevice = new VideoCaptureDevice(deviceMoniker);
this.videoPlayer.VideoSource = this.videoCaptureDevice;
this.videoPlayer.Start();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
}
} /// <summary>
/// Gets video device source collection current available.
/// </summary>
public static IReadOnlyList<MediaInformation> GetVideoDevices()
{
var filterVideoDeviceCollection = new FilterInfoCollection(FilterCategory.VideoInputDevice);
return (from FilterInfo filterInfo
in filterVideoDeviceCollection
select new MediaInformation
{
DisplayName = filterInfo.Name,
MonikerString = filterInfo.MonikerString
}).ToList(); }
}
}

GetVideoDevices方法用来获取所有的摄像头。

Init方法,制定VideoSourcePlayer的VideoCaptureDevice是前置,还是后置摄像头。然后调用VideoSourcePlayer.Start方法就可以实现预览效果了。

最后就可以在MainWindow调用这个类了。

public partial class MainWindow : Window
{
private IReadOnlyList<MediaInformation> mediaDeviceList; public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
this.Closed += MainWindow_Closed;
this.Deactivated += MainWindow_Deactivated;
this.Topmost = true;
} private void MainWindow_Closed(object sender, EventArgs e)
{
//防止视频关闭时画面延迟闪烁
this.Height = ;
this.Width = ;
if (!this.VideoSourcePlayer1.IsDisposed)
{
this.VideoSourcePlayer1.SignalToStop();
this.VideoSourcePlayer1.WaitForStop();
this.VideoSourcePlayer1.Stop();
this.VideoSourcePlayer1.VideoSource = null;
this.VideoSourcePlayer1.Dispose();
} if (!this.VideoSourcePlayer2.IsDisposed)
{
this.VideoSourcePlayer2.SignalToStop();
this.VideoSourcePlayer2.WaitForStop();
this.VideoSourcePlayer2.Stop();
this.VideoSourcePlayer2.VideoSource = null;
this.VideoSourcePlayer2.Dispose();
}
} private void MainWindow_Deactivated(object sender, EventArgs e)
{
this.Topmost = true;
} private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
this.mediaDeviceList = WebcamDevice.GetVideoDevices();
InitFront();
InitBack();
} private void InitFront()
{
if (mediaDeviceList.Count() == )
return; var webCamDevice = new WebcamDevice(this.VideoSourcePlayer1, mediaDeviceList.First().MonikerString);
webCamDevice.Init();
} private void InitBack()
{
if (mediaDeviceList.Count() <= )
return; var webCamDevice = new WebcamDevice(this.VideoSourcePlayer2, mediaDeviceList[].MonikerString);
webCamDevice.Init();
}
}

在Window的Closed事件,需要销毁VideoSourcePlayer对象。

另外指定Topmost=true,可以使这个窗口始终在最前面。

WPF使用AForge实现Webcam预览(一)的更多相关文章

  1. WPF使用AForge实现Webcam预览(二)

    本文主要介绍如何让摄像头预览界面的宽高比始终在16:9. 首先我们需要修改一下上一篇随笔实现的UI界面,让Grid变成一个3*3的九宫格,预览界面位于正中间.Xaml示例代码如下: <Windo ...

  2. 用WPF实现打印及打印预览

    原文:用WPF实现打印及打印预览 应该说,WPF极大地简化了我们的打印输出工作,想过去使用VC++做开发的时候,打印及预览可是一件极麻烦的事情,而现在我不会再使用C++来做Windows的桌面应用了- ...

  3. WPF的路由事件、冒泡事件、隧道事件(预览事件)

    本文摘要: 1:什么是路由事件: 2:中断事件路由: 3:自定义路由事件: 4:为什么需要自定义路由事件: 5:什么是冒泡事件和预览事件(隧道事件): 1:什么是路由事件 WPF中的事件为路由事件,所 ...

  4. [Aaronyang] 写给自己的WPF4.5 笔记15[AyArc诞生-WPF版本绚丽的环状图,Ay制作,AyWindow强势预览]

    原文:[Aaronyang] 写给自己的WPF4.5 笔记15[AyArc诞生-WPF版本绚丽的环状图,Ay制作,AyWindow强势预览]  我的文章一定要做到对读者负责,否则就是失败的文章  -- ...

  5. WPF中的事件及冒泡事件和隧道事件(预览事件)的区别

    WPF快速指导10:WPF中的事件及冒泡事件和隧道事件(预览事件)的区别   WPF快速指导10:WPF中的事件及冒泡事件和隧道事件(预览事件)的区别 本文摘要: 1:什么是路由事件: 2:中断事件路 ...

  6. WPF图片预览之移动、旋转、缩放

    原文:WPF图片预览之移动.旋转.缩放 RT,这个功能比较常见,但凡涉及到图片预览的都跑不了,在说自己的实现方式前,介绍一个好用的控件:Extended.Toolkit中的Zoombox,感兴趣的同学 ...

  7. WPF实现可视化控件打印及打印预览

    打印预览XAML代码: <controls:WindowEx x:Class="SunCreate.Vipf.Client.UI.MapPrintPreview" xmlns ...

  8. WPF 标签预览可以显示图片运行后不显示

    使用<Image HorizontalAlignment="Left" Height="100" Margin="106,111,0,0&quo ...

  9. winForm 打印预览

    自己很少写技术博客,虽然已经干程序员两年多了,winform开发,web开发都干过,不论项目大小对于.net的相关技术也是了解的,如mvc,wcf,wpf,silverlight,socekt通讯,n ...

随机推荐

  1. 学习鸟哥的Linux私房菜笔记(9)——bash1

    一.Shell简介 Shell :命令行解释器,是用户与系统沟通时的媒介 在Unix系统中有各种Shell, Linux采用bash为其默认shell 系统可以使用的shell记录在 /etc/she ...

  2. Java堆/栈/常量池以及String的详细详解(转)------经典易懂系统

    一:在JAVA中,有六个不同的地方可以存储数据: 1. 寄存器(register). 这是最快的存储区,因为它位于不同于其他存储区的地方——处理器内部.但是寄存器的数量极其有限,所以寄存器由编译器根据 ...

  3. javascript数据结构与算法 零(前记+前言)

    前记 这本书Data Structure and Algorithm with Javascript 我将其翻译成<< javascript 数据结构和算法>> 为什么这么翻译 ...

  4. 关于JDBC连接数据库时出现的Public Key Retrieval is not allowed错误

    问题描述 最近在学习MyBatis框架,参考官方的文档通过配置文件的方式已经实现了通过Configuration配置文件和mapper映射文件访问mysql8数据库,于是想试试不使用XML文件去构建S ...

  5. Heterogeneous Self-Organizing Network for Access and Backhaul

    This application discloses methods for creating self-organizing networks implemented on heterogeneou ...

  6. 打开一个很好的介绍Lucene4 FST文章

    我没有看到源代码.看到这个博客了解一些基本的,像笔者下: http://download.csdn.net/download/guanxinquan/7380591 http://blog.sina. ...

  7. IO 字符流学习

    import java.awt.Frame; import java.io.*; public class filewriter { /** * @param args */ public stati ...

  8. Attribute-based identification schemes for objects in internet of things

    Methods and arrangements for object identification. An identification request is received from diffe ...

  9. jQuery.noop

    一个空函数 当你仅仅想要传递一个空函数的时候,就用他吧.这对一些插件作者很有用,当插件提供了一个可选的回调函数接口,那么如果调用的时候没有传递这个回调函数,就用jQuery.noop来代替执行.

  10. End-to end provisioning of storage clouds

    Embodiments discussed in this disclosure provide an integrated provisioning framework that automates ...