我正在尝试创建一个 UWP 应用程序,该应用程序使用笔记本电脑的网络摄像头来处理我想使用 Microsoft Azure Face API 搜索人脸的媒体帧。
我创建了一个运行良好的 MediaCapture 和一个 MediaFrameReader,它会引发问题标题中提到的异常。
你可以在这里看到我的代码:
private async void StartDetection()
{
mediaStream = new InMemoryRandomAccessStream();
MediaEncodingProfile encodingProfile = MediaEncodingProfile.CreateMp4(encodingQuality);
await mediaCapture.StartRecordToStreamAsync(encodingProfile, mediaStream);
var frameSourceGroups = await MediaFrameSourceGroup.FindAllAsync();
MediaFrameSourceGroup selectedGroup = null;
MediaFrameSourceInfo colorSourceInfo = null;
foreach (var sourceGroup in frameSourceGroups)
{
foreach (var sourceInfo in sourceGroup.SourceInfos)
{
if (sourceInfo.MediaStreamType == MediaStreamType.VideoRecord
&& sourceInfo.SourceKind == MediaFrameSourceKind.Color)
{
colorSourceInfo = sourceInfo;
break;
}
}
if (colorSourceInfo != null)
{
selectedGroup = sourceGroup;
break;
}
}
var selectedGroupObjects = frameSourceGroups.Select(group =>
new
{
sourceGroup = group,
colorSourceInfo = group.SourceInfos.FirstOrDefault((sourceInfo) =>
{
// On Xbox/Kinect, omit the MediaStreamType and EnclosureLocation tests
return sourceInfo.MediaStreamType == MediaStreamType.VideoRecord
&& sourceInfo.SourceKind == MediaFrameSourceKind.Color
&& sourceInfo.DeviceInformation?.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Front;
})
}).Where(t => t.colorSourceInfo != null).FirstOrDefault();
selectedGroup = selectedGroupObjects?.sourceGroup;
colorSourceInfo = selectedGroupObjects?.colorSourceInfo;
if (selectedGroup == null)
{
return;
}
var allGroups = await MediaFrameSourceGroup.FindAllAsync();
var eligibleGroups = allGroups.Select(g => new
{
Group = g,
SourceInfos = new MediaFrameSourceInfo[]
{
g.SourceInfos.FirstOrDefault(info => info.SourceKind == MediaFrameSourceKind.Color),
g.SourceInfos.FirstOrDefault(info => info.SourceKind == MediaFrameSourceKind.Depth),
g.SourceInfos.FirstOrDefault(info => info.SourceKind == MediaFrameSourceKind.Infrared),
}
}).Where(g => g.SourceInfos.Any(info => info != null)).ToList();
if (eligibleGroups.Count == 0)
{
System.Diagnostics.Debug.WriteLine("No source group with color, depth or infrared found.");
return;
}
var selectedGroupIndex = 0;
selectedGroup = eligibleGroups[selectedGroupIndex].Group;
colorSourceInfo = eligibleGroups[selectedGroupIndex].SourceInfos[0];
MediaFrameSourceInfo infraredSourceInfo = eligibleGroups[selectedGroupIndex].SourceInfos[1];
MediaFrameSourceInfo depthSourceInfo = eligibleGroups[selectedGroupIndex].SourceInfos[2];
var colorFrameSource = mediaCapture.FrameSources[colorSourceInfo.Id];
var preferredFormat = colorFrameSource.SupportedFormats.Where(format =>
{
return format.VideoFormat.Width >= 1080
&& format.Subtype == "RGB24";
}).FirstOrDefault();
if (preferredFormat == null)
{
return;
}
await colorFrameSource.SetFormatAsync(preferredFormat);
MediaFrameReader mediaFrameReader;
mediaFrameReader = await mediaCapture.CreateFrameReaderAsync(colorFrameSource, preferredFormat.Subtype);
mediaFrameReader.FrameArrived += CheckFrameForFaces;
await mediaFrameReader.StartAsync();
}
private async void CheckFrameForFaces(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
var mediaFrame = sender.TryAcquireLatestFrame(); // -> this is the line that throws the exception
var videoFrame = mediaFrame?.VideoMediaFrame;
var bitmap = videoFrame?.SoftwareBitmap;
WriteableBitmap wb = new WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight);
bitmap.CopyToBuffer(wb.PixelBuffer);
var img = Dlib.LoadImageData<RgbPixel>(wb.PixelBuffer.ToArray(), (uint)wb.PixelHeight, (uint)wb.PixelWidth, 3);
ImageWindow im = new ImageWindow(img);
im.WaitUntilClosed();
}
顺便说一下,这段代码是根据微软文档编写的,可以在这里找到: https ://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/process-media-frames-with -mediaframereader
我唯一更改的是 MediaEncodingSubtype,因为它不适用于 Argb32,所以我使用 Rgb24(我检查了我计算机中所有支持的格式)。而且我认为问题源于这个属性。当我使用子类型 Argb32 初始化 MediaFrameReader 对象时(如您在文档示例中所见),我没有得到任何异常,尽管 SoftwareBitmap 将为空。另一方面,如果我使用 Rgb24(因为 PreferredFormat 有这个子类型)我会得到异常。
我可以显示异常的一些细节:
System.ArgumentException
HResult=0x80070057
Message=Value does not fall within the expected range.
Source=Windows
StackTrace:
at Windows.Media.Capture.Frames.MediaFrameReader.TryAcquireLatestFrame()
at FaceAPI.MainPage.<CheckFrameForFaces>d__17.MoveNext() in P:\Dokumentumok\Suli\BME-VIK_6\Klitech\Házi feladat\KlitechHF\FaceAPI\FaceAPI\MainPage.xaml.cs:line 217