Hololens 2 UWP C# 应用程序:更高分辨率 (2272x1278) 和 NV12 下前置摄像头的问题

问题描述 投票:0回答:1

我正在为 Hololens2 开发 UWP C# 应用程序。我正在尝试使用 MediaCapture 和 MediaFrameReader 访问前置摄像头。 到目前为止,只要我将分辨率保持在 896x504,一切都可以正常工作。一旦我尝试将分辨率更改为 2272x1278,我得到的图像就会损坏。

由于我只对灰度值感兴趣,所以我只是从软件位图中复制亮度值。对于 NV12 格式,这些应该位于缓冲区的开头。当我可视化复制的数据时,我得到如下图所示的图像(此处相机看着一堵白墙)。图像显示出奇怪的对角条纹,但看不到任何东西。 Screenshot

我也尝试过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();
        }
    }    
}
c# uwp hololens nv12-nv21
1个回答
-1
投票

你的问题解决了吗?我遇到了同样的问题,只是相反(896x504)导致了问题。

© www.soinside.com 2019 - 2024. All rights reserved.