原文:如何使用C#创建Windows Webcam应用

最近想用C#写一个camera的应用。搜索了Google和StackOverflow,发现大部分的sample用了WIA或者DirectShow。WIA和DirectShow都没有直接提供C#接口,所以实现起来也比较复杂。试着运行了几个WIA的工程,在Windows10上还不起作用。发现微软提供了一个MediaCapture类,包含了丰富的C#接口,可用于音频,视频。要用这个类,就需要创建一个UWP工程。这里分享下如何使用MediaCapture的C#接口来获取camera的每一帧数据。

微软示例

微软在GitHub上放了大量的UWP示例,里面包含了各种camera的接口使用方法。

在Android中要获取camera的每一帧数据,可以通过onPreviewCallback的回调函数实现。参考CameraFrames这个示例,也可以实现类似的功能。

如何创建Windows Webcam应用

1. 在package.appxmanifest中获取webcam权限:

2. 创建image element用于绘制webcam的预览界面:

3. 通过Image Element初始化FrameRenderer :

_frameRenderer = new FrameRenderer(PreviewImage);

4. 初始化MediaCapture对象:

// Create a new media capture object.
_mediaCapture = new MediaCapture(); var settings = new MediaCaptureInitializationSettings()
{
// Select the source we will be reading from.
SourceGroup = groupModel.SourceGroup, // This media capture has exclusive control of the source.
SharingMode = MediaCaptureSharingMode.ExclusiveControl, // Set to CPU to ensure frames always contain CPU SoftwareBitmap images,
// instead of preferring GPU D3DSurface images.
MemoryPreference = MediaCaptureMemoryPreference.Cpu, // Capture only video. Audio device will not be initialized.
StreamingCaptureMode = StreamingCaptureMode.Video,
}; try
{
// Initialize MediaCapture with the specified group.
// This can raise an exception if the source no longer exists,
// or if the source could not be initialized.
await _mediaCapture.InitializeAsync(settings);
_logger.Log($"Successfully initialized MediaCapture for {groupModel.DisplayName}");
}
catch (Exception exception)
{
_logger.Log(exception.Message);
DisposeMediaCapture();
}

5. 使用DeviceWatcher 列出所有设备:

var deviceSelector = MediaFrameSourceGroup.GetDeviceSelector();
_watcher = DeviceInformation.CreateWatcher(deviceSelector);
_watcher.Added += Watcher_Added;
_watcher.Removed += Watcher_Removed;
_watcher.Updated += Watcher_Updated;
_watcher.Start(); private async void Watcher_Added(DeviceWatcher sender, DeviceInformation args)
{
await AddDeviceAsync(args.Id);
} private async Task AddDeviceAsync(string id)
{
var group = await MediaFrameSourceGroup.FromIdAsync(id);
if (group != null)
{
await _dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
_sourceCollection.Add(new FrameSourceGroupModel(group));
});
}
}

6. 针对用户的选择更新设备源:

_mediaCapture.FrameSources.TryGetValue(info.SourceInfo.Id, out _source);

7. 通过MediaFrameReader 注册回调函数:

if (_source != null)
{
_reader = await _mediaCapture.CreateFrameReaderAsync(_source);
_reader.FrameArrived += Reader_FrameArrived;
}

8. 启动webcam:

MediaFrameReaderStartStatus result = await _reader.StartAsync();

9. 读取并绘制每一帧数据:

private void Reader_FrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
// TryAcquireLatestFrame will return the latest frame that has not yet been acquired.
// This can return null if there is no such frame, or if the reader is not in the
// "Started" state. The latter can occur if a FrameArrived event was in flight
// when the reader was stopped.
using (var frame = sender.TryAcquireLatestFrame())
{
_frameRenderer.ProcessFrame(frame);
}
} public void ProcessFrame(MediaFrameReference frame)
{
var softwareBitmap = FrameRenderer.ConvertToDisplayableImage(frame?.VideoMediaFrame); if (softwareBitmap != null)
{
// Swap the processed frame to _backBuffer and trigger UI thread to render it
softwareBitmap = Interlocked.Exchange(ref _backBuffer, softwareBitmap); // UI thread always reset _backBuffer before using it. Unused bitmap should be disposed.
softwareBitmap?.Dispose(); // Changes to xaml ImageElement must happen in UI thread through Dispatcher
var task = _imageElement.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
async () =>
{
// Don't let two copies of this task run at the same time.
if (_taskRunning)
{
return;
}
_taskRunning = true; // Keep draining frames from the backbuffer until the backbuffer is empty.
SoftwareBitmap latestBitmap;
while ((latestBitmap = Interlocked.Exchange(ref _backBuffer, null)) != null)
{
var imageSource = (SoftwareBitmapSource)_imageElement.Source;
await imageSource.SetBitmapAsync(latestBitmap);
latestBitmap.Dispose();
} _taskRunning = false;
});
}
}

参考

Basic photo, video, and audio capture with MediaCapture

源码

https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/CameraFrames

如何使用C#创建Windows Webcam应用的更多相关文章

  1. 简单的Windows Webcam应用:Barcode Reader

    原文:简单的Windows Webcam应用:Barcode Reader 在Windows上用WinForm创建一个Webcam应用需要用到DirectShow.DirectShow没有提供C#的接 ...

  2. 用C#创建Windows服务(Windows Services)

    用C#创建Windows服务(Windows Services) 学习:  第一步:创建服务框架 创建一个新的 Windows 服务项目,可以从Visual C# 工程中选取 Windows 服务(W ...

  3. 玩转Windows服务系列——创建Windows服务

    创建Windows服务的项目 新建项目->C++语言->ATL->ATL项目->服务(EXE) 这样就创建了一个Windows服务项目. 生成的解决方案包含两个项目:Servi ...

  4. .Net创建windows服务入门

    本文主要记录学习.net 如何创建windows服务. 1.创建一个Windows服务程序 2.新建安装程序 3.修改service文件 代码如下 protected override void On ...

  5. C# 创建Windows服务

    创建windows服务项目   2 右键点击Service1.cs,查看代码, 用于编写操作逻辑代码 3 代码中OnStart用于执行服务事件,一般采用线程方式执行方法,便于隔一段事件执行一回 END ...

  6. 使用.net 创建windows service

    最近公司项目需要,写了个windows 服务,windows 服务的内容可以在VS 中新建一个"windows服务项目", (1)服务中的主要代码: public partial ...

  7. 使用Topshelf创建Windows服务

    概述 Topshelf是创建Windows服务的另一种方法,老外的一篇文章Create a .NET Windows Service in 5 steps with Topshelf通过5个步骤详细的 ...

  8. C#创建windows服务列表

    转载自:http://www.cnblogs.com/sorex/archive/2012/05/16/2502001.html Windows Service这一块并不复杂,但是注意事项太多了,网上 ...

  9. [转]C#创建Windows服务与安装

    本文档用于创建windows服务说明,使用vs2010系统平台 创建项目 1 创建windows服务项目 2 右键点击Service1.cs,查看代码, 用于编写操作逻辑代码 3 代码中OnStart ...

随机推荐

  1. DDoS ATTACK PROCESSING APPARATUS AND METHOD IN OPENFLOW SWITCH

    An OpenFlow switch in an OpenFlow environment includes an attack determination module to collect sta ...

  2. ts demuxer的加入记录

    文件夹 1 初衷 2 ts demux的功能介绍 1 初衷 之前打算给dtplayer加入一些亮点功能,最初的想法是:bt下载播放 + hls支持 bt下载因为以来libtorrent库,尽管搞懂了怎 ...

  3. linux下Java程序中插入DB中国的数据乱码问题

    首先,插入到DB数据,在Linux在查询时,现场展示??. 再次,在windows连接到db上,查看的结果并非乱码. 改动Eclipse软件中的编码:如上图:windows菜单->prefere ...

  4. Cordova热更新和App升级 - 简书

    原文:Cordova热更新和App升级 - 简书 公司的cordova项目前段时间增加了热更新功能,自己第一次做的时候在网上查找了很多资料,有的资料写的并不全面遇到了很多坑.因此总结一些在开发过程中遇 ...

  5. XMPP开发adiumclient登陆

    我写在前面client它已经实现了登陆,我用下面的adium要登录落实的朋友加入,而自己写的client在聊天帐号. 第一次登录时adium工欲善其事,必先例如,下面的配置 保存后.你会发现自己的账号 ...

  6. 弄App Store提示和技巧推荐

    众所周知上苹果的主页推荐是对产品最佳(高曝光率+零广告费)推广,然而苹果却对选择的方式和规则讳莫如深. 下面是搜集的一些获得推荐的开发人员的经验. 1. 产品要新颖.且质量上乘.这个质量包括非常多细节 ...

  7. 【从翻译mos文章】采用高速全扫描索引(index ffs) 为了避免全表扫描

    采用高速全扫描索引(index ffs) 为了避免全表扫描 参考原始: Index Fast Full Scan Usage To Avoid Full Table Scans (Doc ID 701 ...

  8. WinEdt && LaTex(四)—— 自定义新命令(newcommand、def)

    1. 新建命令 使用如下的命令:\newcommand{name}[num]{definition}: 该命令(newcommand)有两个参数,第一个 name 是你想要建立的命令的名称,第二个def ...

  9. OpenGL(七) 光照模型及设置

    OpenGL把现实世界中的光照系统近似归为三部分,分别是光源.材质和光照环境. 光源就是光的来源,是"光"这种物质的提供者: 材质是指被光源照射的物体的表面的反射.漫反射(Open ...

  10. kbmmw 中XML 操作入门(跨平台,而且可以与JSON,YAML,BSON 直接互相转换)

    delphi 很早以前就自带了xml 的操作,最新版里面有三种XML 解释器,一种是MSXML,看名字就知道 这个是微软自带的,这个据delphi 官方称是速度是最快的,但是只能在windows 上使 ...