Я использую MediaCapture
для предварительного просмотра камеры на экране, которая работает нормально.
Однако мне нужно получить доступ к текущим кадрам в моем приложении. Поэтому я добавил FrameReader
к MediaCapture
, чтобы получить событие Reader_FrameArrived.
Таким образом, событие работает, однако само растровое изображение всегда равно нулю.
Я реализовал обратный вызов ecent, как показано в примерах:
var mediaFrameReference = sender.TryAcquireLatestFrame();
var videoMediaFrame = mediaFrameReference?.VideoMediaFrame;
var softwareBitmap = videoMediaFrame?.SoftwareBitmap;
if (softwareBitmap != null)
{
Debug.WriteLine("here");
}
else
{
return;
}
и вот как я инициализирую читатель:
var frameSourceGroups = await MediaFrameSourceGroup.FindAllAsync();
var allGroups = await MediaFrameSourceGroup.FindAllAsync();
var eligibleGroups = allGroups.Select(g => new
{
Group = g,
// For each source kind, find the source which offers that kind of media frame,
// or null if there is no such source.
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; // Select the first eligible group
MediaFrameSourceGroup selectedGroup = eligibleGroups[selectedGroupIndex].Group;
MediaFrameSourceInfo colorSourceInfo = eligibleGroups[selectedGroupIndex].SourceInfos[0];
MediaFrameSourceInfo infraredSourceInfo = eligibleGroups[selectedGroupIndex].SourceInfos[1];
MediaFrameSourceInfo depthSourceInfo = eligibleGroups[selectedGroupIndex].SourceInfos[2];
//_mediaCapture.FrameSources.TryGetValue(cameraDevice.Id, out _source);
var colorFrameSource = _mediaCapture.FrameSources[colorSourceInfo.Id];
if (colorFrameSource != null)
{
_reader = await _mediaCapture.CreateFrameReaderAsync(colorFrameSource, MediaEncodingSubtypes.Argb32);
_reader.FrameArrived += Reader_FrameArrived;
MediaFrameReaderStartStatus result = await _reader.StartAsync();
Debug.WriteLine(result.ToString());
}
Любые идеи, почему растровое изображение может быть нулевым?
Я использую MediaCapture для предварительного просмотра камеры на экране, которая работает нормально.
Для сценария мы предлагаем вам использовать растровое изображение захвата класса MediaCapture
, оно содержит метод GetPreviewFrameAsync, который получает кадр предварительного просмотра с устройства захвата, а затем преобразует его в SoftwareBitmap
.
private async Task GetPreviewFrameAsSoftwareBitmapAsync()
{
// Get information about the preview
var previewProperties = _mediaCapture.VideoDeviceController.GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;
// Create the video frame to request a SoftwareBitmap preview frame
var videoFrame = new VideoFrame(BitmapPixelFormat.Bgra8, (int)previewProperties.Width, (int)previewProperties.Height);
// Capture the preview frame
using (var currentFrame = await _mediaCapture.GetPreviewFrameAsync(videoFrame))
{
// Collect the resulting frame
SoftwareBitmap previewFrame = currentFrame.SoftwareBitmap;
// Show the frame information
FrameInfoTextBlock.Text = String.Format("{0}x{1} {2}", previewFrame.PixelWidth, previewFrame.PixelHeight, previewFrame.BitmapPixelFormat);
// Add a simple green filter effect to the SoftwareBitmap
if (GreenEffectCheckBox.IsChecked == true)
{
ApplyGreenFilter(previewFrame);
}
// Show the frame (as is, no rotation is being applied)
if (ShowFrameCheckBox.IsChecked == true)
{
// Create a SoftwareBitmapSource to display the SoftwareBitmap to the user
var sbSource = new SoftwareBitmapSource();
await sbSource.SetBitmapAsync(previewFrame);
// Display it in the Image control
PreviewFrameImage.Source = sbSource;
}
// Save the frame (as is, no rotation is being applied)
if (SaveFrameCheckBox.IsChecked == true)
{
var file = await _captureFolder.CreateFileAsync("PreviewFrame.jpg", CreationCollisionOption.GenerateUniqueName);
Debug.WriteLine("Saving preview frame to " + file.Path);
await SaveSoftwareBitmapAsync(previewFrame, file);
}
}
}
А вот и официальный пример кода, на который вы можете сослаться напрямую.
В приведенном выше примере кода не используется FrameReader
, вы можете вызвать метод GetPreviewFrameAsSoftwareBitmapAsync
, чтобы напрямую получить растровое изображение.
да, но есть ли способ, как я всегда буду получать новый кадр через событие/обратный вызов здесь? Я не хочу всегда вызывать функцию в цикле
Да, я проверил ваш код, похоже, он взят из примера кода Come Frame. он использует ConvertToDisplayableImage
, чтобы получить изображение из кадра. Пожалуйста, посмотрите.
спасибо за предложение. есть ли событие/обратный вызов, который я могу использовать для получения каждого нового кадра? Или мне все еще нужен FrameReader для этого?