我正在为 Hololens2 开发 UWP C# 应用程序。我正在尝试使用 MediaCapture 和 MediaFrameReader 访问前置摄像头。 到目前为止,只要我将分辨率保持在 896x504,一切都可以正常工作。一旦我尝试将分辨率更改为 2272x1278,我得到的图像就会损坏。
由于我只对灰度值感兴趣,所以我只是从软件位图中复制亮度值。对于 NV12 格式,这些应该位于缓冲区的开头。当我可视化复制的数据时,我得到如下图所示的图像(此处相机看着一堵白墙)。图像显示出奇怪的对角条纹,但看不到任何东西。
我也尝试过YUV2格式,效果很好,但是复制像素数据需要更多时间。
我错过了什么吗?
[编辑]我在 Github 上放置了一个演示应用程序来展示问题。
这是我用来访问像素数据的一些代码片段:
string deviceId = await GetDeviceId();
var mediaInitSettings = new MediaCaptureInitializationSettings { VideoDeviceId = deviceId };
IReadOnlyList<MediaCaptureVideoProfile> profiles = MediaCapture.FindAllVideoProfiles(deviceId);
var match = (from profile in profiles
from desc in profile.SupportedRecordMediaDescription
where desc.Subtype == "NV12" && desc.Width == 2272 && desc.Height == 1278 && Math.Abs(desc.FrameRate - 30) < Tolerance
select new { profile, desc}).FirstOrDefault();
if (match != null)
{
mediaInitSettings.VideoProfile = match.profile;
mediaInitSettings.RecordMediaDescription = match.desc;
mediaInitSettings.SharingMode = MediaCaptureSharingMode.ExclusiveControl;
mediaInitSettings.MemoryPreference = MediaCaptureMemoryPreference.Cpu;
}
else
{
mediaInitSettings.VideoProfile = profiles[0];
}
_mediaCapture = new MediaCapture();
await _mediaCapture.InitializeAsync(mediaInitSettings);
const MediaStreamType mediaStreamType = MediaStreamType.VideoRecord;
CameraParameters parameters = new CameraParameters(_cameraProfile);
MediaFrameSource source = _mediaCapture.FrameSources.Values.Single(frameSource => frameSource.Info.MediaStreamType == mediaStreamType);
var preferredFormat = source.SupportedFormats.Where(format =>
format.VideoFormat.Height == parameters.CameraResolutionHeight
&&
format.VideoFormat.Width == parameters.CameraResolutionWidth
&&
Math.Round(format.FrameRate.Numerator / format.FrameRate.Denominator - parameters.FrameRate) < Tolerance
&&
format.Subtype == "NV12");
var selectedFormat = preferredFormat.FirstOrDefault();
await source.SetFormatAsync(selectedFormat);
_frameReader = await _mediaCapture.CreateFrameReaderAsync(source, selectedFormat.Subtype);
_frameReader.FrameArrived += OnFrameArrived;
private async void OnFrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
if (sender == null) throw new ArgumentNullException(nameof(sender));
if (args == null) throw new ArgumentNullException(nameof(args));
using (MediaFrameReference mediaFrameReference = sender.TryAcquireLatestFrame())
{
if (mediaFrameReference == null) return;
var videoMediaFrame = mediaFrameReference.VideoMediaFrame;
var softwareBitmap = videoMediaFrame?.SoftwareBitmap;
if (softwareBitmap != null)
{
var width = softwareBitmap.PixelWidth;
var height = softwareBitmap.PixelHeight;
// copy only luminance plane of NV12
byte[] rawPixelData = new byte[width * height];
using (var buffer = softwareBitmap.LockBuffer(BitmapBufferAccessMode.Read))
using (var reference = buffer.CreateReference())
unsafe
{
byte* pixelData;
uint capacity;
((IMemoryBufferByteAccess)reference).GetBuffer(out pixelData, out capacity);
Marshal.Copy((IntPtr)pixelData, rawPixelData, 0, rawPixelData.Length);
}
FrameArrived?.Invoke(this, new FrameArrivedEventArgs(rawPixelData, width, height));
softwareBitmap.Dispose();
}
}
}
你的问题解决了吗?我遇到了同样的问题,只是相反(896x504)导致了问题。