UWP Kinect V2 保持帧速率恒定(30fps)
UWP Kinect V2 keep frame rate constant (30fps)
我正在 UWP 中处理从 Kinect v2(彩色和红外)接收的帧。该程序在远程计算机 (XBOX One S) 上运行。主要目标是获取帧并将它们以 30 fps 的速度写入磁盘,用于 Color 和 IR,以便稍后进一步处理它们。
我正在使用以下代码检查帧率:
public MainPage()
{
this.InitialiseFrameReader(); // initialises MediaCapture for IR and Color
}
const int COLOR_SOURCE = 0;
const int IR_SOURCE = 1;
private async void InitialiseFrameReader()
{
await CleanupMediaCaptureAsync();
var allGroups = await MediaFrameSourceGroup.FindAllAsync();
if (allGroups.Count == 0)
{
return;
}
_groupSelectionIndex = (_groupSelectionIndex + 1) % allGroups.Count;
var selectedGroup = allGroups[_groupSelectionIndex];
var kinectGroup = selectedGroup;
try
{
await InitializeMediaCaptureAsync(kinectGroup);
}
catch (Exception exception)
{
_logger.Log($"MediaCapture initialization error: {exception.Message}");
await CleanupMediaCaptureAsync();
return;
}
// Set up frame readers, register event handlers and start streaming.
var startedKinds = new HashSet<MediaFrameSourceKind>();
foreach (MediaFrameSource source in _mediaCapture.FrameSources.Values.Where(x => x.Info.SourceKind == MediaFrameSourceKind.Color || x.Info.SourceKind == MediaFrameSourceKind.Infrared)) //
{
MediaFrameSourceKind kind = source.Info.SourceKind;
MediaFrameSource frameSource = null;
int frameindex = COLOR_SOURCE;
if (kind == MediaFrameSourceKind.Infrared)
{
frameindex = IR_SOURCE;
}
// Ignore this source if we already have a source of this kind.
if (startedKinds.Contains(kind))
{
continue;
}
MediaFrameSourceInfo frameInfo = kinectGroup.SourceInfos[frameindex];
if (_mediaCapture.FrameSources.TryGetValue(frameInfo.Id, out frameSource))
{
// Create a frameReader based on the source stream
MediaFrameReader frameReader = await _mediaCapture.CreateFrameReaderAsync(frameSource);
frameReader.FrameArrived += FrameReader_FrameArrived;
_sourceReaders.Add(frameReader);
MediaFrameReaderStartStatus status = await frameReader.StartAsync();
if (status == MediaFrameReaderStartStatus.Success)
{
startedKinds.Add(kind);
}
}
}
}
private async Task InitializeMediaCaptureAsync(MediaFrameSourceGroup sourceGroup)
{
if (_mediaCapture != null)
{
return;
}
// Initialize mediacapture with the source group.
_mediaCapture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings
{
SourceGroup = sourceGroup,
SharingMode = MediaCaptureSharingMode.SharedReadOnly,
StreamingCaptureMode = StreamingCaptureMode.Video,
MemoryPreference = MediaCaptureMemoryPreference.Cpu
};
await _mediaCapture.InitializeAsync(settings);
}
private void FrameReader_FrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
using (var frame = sender.TryAcquireLatestFrame())
{
if (frame != null)
{
//Settings.cameraframeQueue.Enqueue(null, frame.SourceKind.ToString(), frame.SystemRelativeTime.Value); //Add to Queue to process frame
Debug.WriteLine(frame.SourceKind.ToString() + " : " + frame.SystemRelativeTime.ToString());
}
}
}
我正在尝试调试应用程序以检查帧速率,因此我删除了进一步的处理。
不知道是我计算的不对还是其他什么地方不对。
例如,从 04:37:06 到 04:37:48 的系统相对时间给出:
IR:
Fps(发生)
31(1)
30(36)
29(18)
28(4)
颜色:
Fps(发生)
30(38)
29(18)
28(3)
我希望此帧速率保持恒定 (30 fps) 并对齐,以便 IR 和颜色以及当时相同的帧数。
这不包括任何附加代码。一旦我有了进程队列或任何类型的代码,fps 就会下降,范围从 15 到 30。
谁能帮我解决这个问题?
谢谢。
更新:
经过一些测试和变通后,我注意到 PC 产生 30fps 但 XBOX One(远程设备)在调试模式下产生非常低的 fps。然而,当 运行 它处于发布模式但分配给 UWP 应用程序的内存非常低时,这确实会有所改善。
https://docs.microsoft.com/en-us/windows/uwp/xbox-apps/system-resource-allocation
Xbox One 的最大可用内存为 1 GB 用于应用程序,5 GB 用于游戏。
https://docs.microsoft.com/en-us/windows/uwp/xbox-apps/system-resource-allocation
而在 PC 中 fps 是 30(因为内存没有这样的限制)。
这会导致帧率下降。但是,当 运行 在发布模式下或发布到 MS Store 时,fps 确实有所提高。
我正在 UWP 中处理从 Kinect v2(彩色和红外)接收的帧。该程序在远程计算机 (XBOX One S) 上运行。主要目标是获取帧并将它们以 30 fps 的速度写入磁盘,用于 Color 和 IR,以便稍后进一步处理它们。
我正在使用以下代码检查帧率:
public MainPage()
{
this.InitialiseFrameReader(); // initialises MediaCapture for IR and Color
}
const int COLOR_SOURCE = 0;
const int IR_SOURCE = 1;
private async void InitialiseFrameReader()
{
await CleanupMediaCaptureAsync();
var allGroups = await MediaFrameSourceGroup.FindAllAsync();
if (allGroups.Count == 0)
{
return;
}
_groupSelectionIndex = (_groupSelectionIndex + 1) % allGroups.Count;
var selectedGroup = allGroups[_groupSelectionIndex];
var kinectGroup = selectedGroup;
try
{
await InitializeMediaCaptureAsync(kinectGroup);
}
catch (Exception exception)
{
_logger.Log($"MediaCapture initialization error: {exception.Message}");
await CleanupMediaCaptureAsync();
return;
}
// Set up frame readers, register event handlers and start streaming.
var startedKinds = new HashSet<MediaFrameSourceKind>();
foreach (MediaFrameSource source in _mediaCapture.FrameSources.Values.Where(x => x.Info.SourceKind == MediaFrameSourceKind.Color || x.Info.SourceKind == MediaFrameSourceKind.Infrared)) //
{
MediaFrameSourceKind kind = source.Info.SourceKind;
MediaFrameSource frameSource = null;
int frameindex = COLOR_SOURCE;
if (kind == MediaFrameSourceKind.Infrared)
{
frameindex = IR_SOURCE;
}
// Ignore this source if we already have a source of this kind.
if (startedKinds.Contains(kind))
{
continue;
}
MediaFrameSourceInfo frameInfo = kinectGroup.SourceInfos[frameindex];
if (_mediaCapture.FrameSources.TryGetValue(frameInfo.Id, out frameSource))
{
// Create a frameReader based on the source stream
MediaFrameReader frameReader = await _mediaCapture.CreateFrameReaderAsync(frameSource);
frameReader.FrameArrived += FrameReader_FrameArrived;
_sourceReaders.Add(frameReader);
MediaFrameReaderStartStatus status = await frameReader.StartAsync();
if (status == MediaFrameReaderStartStatus.Success)
{
startedKinds.Add(kind);
}
}
}
}
private async Task InitializeMediaCaptureAsync(MediaFrameSourceGroup sourceGroup)
{
if (_mediaCapture != null)
{
return;
}
// Initialize mediacapture with the source group.
_mediaCapture = new MediaCapture();
var settings = new MediaCaptureInitializationSettings
{
SourceGroup = sourceGroup,
SharingMode = MediaCaptureSharingMode.SharedReadOnly,
StreamingCaptureMode = StreamingCaptureMode.Video,
MemoryPreference = MediaCaptureMemoryPreference.Cpu
};
await _mediaCapture.InitializeAsync(settings);
}
private void FrameReader_FrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
using (var frame = sender.TryAcquireLatestFrame())
{
if (frame != null)
{
//Settings.cameraframeQueue.Enqueue(null, frame.SourceKind.ToString(), frame.SystemRelativeTime.Value); //Add to Queue to process frame
Debug.WriteLine(frame.SourceKind.ToString() + " : " + frame.SystemRelativeTime.ToString());
}
}
}
我正在尝试调试应用程序以检查帧速率,因此我删除了进一步的处理。
不知道是我计算的不对还是其他什么地方不对。
例如,从 04:37:06 到 04:37:48 的系统相对时间给出:
IR: Fps(发生)
31(1) 30(36) 29(18) 28(4)
颜色: Fps(发生)
30(38) 29(18) 28(3)
我希望此帧速率保持恒定 (30 fps) 并对齐,以便 IR 和颜色以及当时相同的帧数。
这不包括任何附加代码。一旦我有了进程队列或任何类型的代码,fps 就会下降,范围从 15 到 30。
谁能帮我解决这个问题?
谢谢。
更新:
经过一些测试和变通后,我注意到 PC 产生 30fps 但 XBOX One(远程设备)在调试模式下产生非常低的 fps。然而,当 运行 它处于发布模式但分配给 UWP 应用程序的内存非常低时,这确实会有所改善。 https://docs.microsoft.com/en-us/windows/uwp/xbox-apps/system-resource-allocation
Xbox One 的最大可用内存为 1 GB 用于应用程序,5 GB 用于游戏。 https://docs.microsoft.com/en-us/windows/uwp/xbox-apps/system-resource-allocation
而在 PC 中 fps 是 30(因为内存没有这样的限制)。
这会导致帧率下降。但是,当 运行 在发布模式下或发布到 MS Store 时,fps 确实有所提高。