WPF使用AForge实现Webcam预览(一)
本文简略地介绍一下如果使用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 = 0; this.Width = 0; 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() == 0) return; var webCamDevice = new WebcamDevice(this.VideoSourcePlayer1, mediaDeviceList.First().MonikerString); webCamDevice.Init(); } private void InitBack() { if (mediaDeviceList.Count() <= 1) return; var webCamDevice = new WebcamDevice(this.VideoSourcePlayer2, mediaDeviceList[1].MonikerString); webCamDevice.Init(); } }
在Window的Closed事件,需要销毁VideoSourcePlayer对象。
另外指定Topmost=true,可以使这个窗口始终在最前面。