And*_*ran 7 camera infrared ms-media-foundation windows-hello c++-winrt
Windows Hello 摄像头使用红外摄像头和红外发射器,并将两者结合起来感测帧中的深度。它类似于 Apple 的 FaceID 或 Xbox Kinect 中的技术。访问 Windows Hello 摄像头的深度传感功能对于研究人员和应用程序开发人员来说可能非常有价值。
\n我能够创建一个应用程序,该应用程序能够访问嵌入在启用 Windows Hello 的网络摄像头中的红外摄像头。然而我发现红外发射器的行为不一致。我已将代码发布到上面链接的 github 存储库中。
\n在我能够访问红外摄像机的每一帧后,我意识到我的摄像机没有打开Infrared Torch(摄像机红外发射器 LED)。但我知道红外手电筒可以工作,因为当我使用 Windows Hello 的面部识别功能时,红外手电筒确实会打开。
我发现驱动程序级别的 Windows 红外摄像头具有以下红外手电筒模式:
\n| 触摸模式 | 描述 |
|---|---|
| KSCAMERA_EXTENDEDPROP_IRTORCHMODE_OFF | Off |
| KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALWAYS_ON | Always on |
| KSCAMERA_EXTENDEDPROP_IRTORCHMODE_ALTERNATING_FRAME_ILLUMINATION | On for every other frame |
参考: https: //learn.microsoft.com/en-us/windows-hardware/drivers/stream/ksproperty-cameracontrol-extended-irtorchmode。
\nOn for every other frame,但在其他摄像机中,例如 NexiGo HelloCam N930W 摄像机,默认值为关闭,这需要以某种方式将其打开。理论上,媒体基础 API 可以使用 VideoDeviceController 类中的 InfraredTorchControl 类来更改这些值,该类可从 MediaCapture 类访问,如下所示:
\nauto infraredTorchControl = m_mediaCapture.VideoDeviceController().InfraredTorchControl();\nif(infraredTorchControl.IsSupported()){\n infraredTorchControl.CurrentMode(winrt::Windows::Media::Devices::InfraredTorchMode::On);\n}\nRun Code Online (Sandbox Code Playgroud)\n但问题就从这部分代码开始。当我尝试访问InfraredTorchControl时,API 表示不支持它。我通读了VideoDeviceController Class 文档,它指出某些驱动程序可能要求相机设备处于预览状态,然后才能确定支持哪些控件。所以我尝试用几种不同的方式来解决这个问题:
\n首先,我开发了一个没有 UWP 界面的 WinRT 应用程序。由于 VideoDeviceController 文档说相机需要处于预览状态,因此我尝试MediaCapture使用StartPreviewAsync(). 但这里的问题是我需要将源/接收器(MediaCapture 类)设置为一个CaptureElement类,因此我尝试实例化 CaptureElement 类并设置源以满足该要求。
#include "winrt/Windows.UI.Xaml.Controls.h";\nusing namespace winrt::Windows::UI::Xaml::Controls;\n\nCaptureElement captureElement;\ncaptureElement.Source(m_mediaCapture);\nm_mediaCapture.StartPreviewAsync();\nm_mediaCapture.StopPreviewAsync();\nRun Code Online (Sandbox Code Playgroud)\n但它不起作用,它会抛出以下错误:
\nWinRT originate error: \'Input format unsupported\'.\nWinRT originate error: \'No suitable transform was found to encode or decode the content.\'.\nRun Code Online (Sandbox Code Playgroud)\n发生此错误的最可能原因是CaptureElement不支持红外摄像机提供的格式,即 L8(一种每像素 8 位的定点像素格式,其中唯一的组成部分是亮度。 )。如果有人知道如何解决这个问题,请发表评论。
我认为可能会弹出此错误,因为我正在开发没有 UWP 界面的 WinRT 应用程序,因此我尝试使用模板实现一个简单的 UWP 应用程序,Blank App (C++/WinRT) 以检查是否可以直接将 CaptureElement 与 XAML 文件一起使用。
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">\n <CaptureElement x:Name="MyPreview" Stretch="UniformToFill" />\n <Button x:Name="myButton" Click="ClickHandler">Click Me</Button>\n </StackPanel>\nRun Code Online (Sandbox Code Playgroud)\nMyPreview.Source = m_mediaCapture;\nRun Code Online (Sandbox Code Playgroud)\n不幸的是,这种类型的应用程序也出现了同样的错误,所以我放弃了这是我原来的应用程序有问题的想法。
\nWinRT originate error : \'Input format unsupported\'.\nWinRT originate error: \'No suitable transform was found to encode or decode the content.\'.\nRun Code Online (Sandbox Code Playgroud)\n该解决方案是我理解最少的解决方案,但对于没有用户界面的应用程序来说,它似乎是最正确的。简而言之,这个想法是创建一个可由 MediaCapture 类函数接受的自定义媒体接收器,如下所示:
\nStartPreviewToCustomSinkAsync(MediaEncodingProfile, IMediaExtension)StartPreviewToCustomSinkAsync(MediaEncodingProfile, String, IPropertySet)理论上允许自定义媒体接收器作为参数传递。但问题是我找不到任何指定如何创建此自定义媒体接收器的文档。我只找到了这个教程:https://www.codeproject.com/Tips/772038/Custom-Media-Sink-for-Use-with-Media-Foundation-To。本教程使用 C++/CX,因此我尝试将该代码转换为 C++/WinRT,但未成功。
\n首先,我不明白为什么我需要设置一个媒体接收器才能启动相机的预览状态。我只需要修改相机的值,就像 InfraredTorch 模式一样。我不需要显示此时相机的输出。
\n我想到的第二个结论是,即使满足媒体接收器要求,Microsoft Media Foundation Platform API 也不\xe2\x80\x99 不支持红外摄像机的预览状态。由于 CaptureElement 显然不支持图像格式(L8)。但我不确定,因为 InfraredTorchControl 文档中有一个带有 CaptureElement 类的示例。
\n第三,解决这个问题的一种方法似乎是使用自定义媒体接收器,这需要非常深入的知识,并且几乎没有文档解释如何将所有部分组合在一起。
\n最后,我认为作为最后一个选择,我们可以考虑使用 DeviceMFT 直接访问红外摄像头驱动程序的可能性。
\n