MediaFoundation дает четыре камеры в одном кадре - PullRequest
1 голос
/ 28 января 2020

Я пытаюсь получить глубину камеры HoloLens 2 с помощью MediaFoundation. Затем этот поток связан с UWP и MediaFoundation.

С этим кодом инициализации C# (имеется некоторый мой код C ++ для обработки конвейера MediaFoundation), я могу получить следующего захваченного изображения , который я изменил, используя gimp, чтобы подчеркнуть низкие значения (т. Е. Вставленное изображение будет ярче).

/// <summary>
    /// Asynchronously create a Hand Detector with the first depth camera found
    /// </summary>
    /// <param name="id">The ID of the device to look for if needed. If NULL, a device with "depth" capabilities will be randomly choose.</param>
    /// <returns>The asynchronous task</returns>
    public static async Task<HandDetector> CreateAsync(String id=null)
    {
        Debug.WriteLine("Initialize the hand detector");

        //Search for the correct media frame source
        MediaFrameSourceGroup selectedFrameSourceGroup = null;
        MediaFrameSourceInfo  selectedFrameSourceInfo  = null;

        IReadOnlyList<MediaFrameSourceGroup> allFrameSourceGroups = await MediaFrameSourceGroup.FindAllAsync();

        Debug.WriteLine($"Found {allFrameSourceGroups.Count} frame sources...");

        foreach (MediaFrameSourceGroup group in allFrameSourceGroups)
        {
            Debug.WriteLine($"Group: {group.DisplayName}");
            Debug.WriteLine($"Found {group.SourceInfos.Count} source infos...");
            foreach(MediaFrameSourceInfo info in group.SourceInfos)
            {
                //Debug.WriteLine($"{info.SourceKind} : {info.MediaStreamType} -> {info.DeviceInformation.EnclosureLocation.Panel}");
                //If an ID is given
                if ((id == null || info.DeviceInformation.Id == id) && (info.MediaStreamType == MediaStreamType.VideoPreview || info.MediaStreamType == MediaStreamType.VideoRecord))
                {
                    //Check the depth capabilities
                    if (info.SourceKind == MediaFrameSourceKind.Depth)
                    {                            
                        selectedFrameSourceGroup = group;
                        selectedFrameSourceInfo = info;

                        Debug.WriteLine($"Found Device : {info.DeviceInformation.Name}:{info.DeviceInformation.Id}");
                    }
                }

                if (selectedFrameSourceGroup != null)
                    break;
            }
            if(selectedFrameSourceGroup != null)
                break;
        }

        if (selectedFrameSourceGroup == null)
        {
            Debug.WriteLine("No frame source available found");
            return null;
        }

        HandDetector HandDetector = new HandDetector(selectedFrameSourceGroup, selectedFrameSourceInfo);
        return HandDetector;
    }

    /// <summary>
    /// Creates asynchronously the Media Capture which will process the depth stream images
    /// </summary>
    /// <param name="clbk">The Callback object to call when the hand detection status changes.</param>
    /// <returns>The asynchronous task</returns>
    public async Task InitializeAsync(IHDMediaSinkClbk clbk)
    {
        //Create the media capture
        Debug.WriteLine("Creating a media capture...");
        m_mediaCapture = new MediaCapture();
        await m_mediaCapture.InitializeAsync(new MediaCaptureInitializationSettings()
        {
            SourceGroup             = m_mediaGroup,
            SharingMode             = MediaCaptureSharingMode.SharedReadOnly,
            MemoryPreference        = MediaCaptureMemoryPreference.Auto,   //For the Hololens, MediaCaptureMemoryPreference.CPU does not work
            StreamingCaptureMode    = StreamingCaptureMode.Video
        });

        //Find a correct video profile with the best capabilities (resolution)
        Debug.WriteLine("Search a video profile...");
        VideoEncodingProperties videoProfile = null;
        var mediaProperties = m_mediaCapture.VideoDeviceController.GetAvailableMediaStreamProperties(MediaStreamType.VideoPreview);
        UInt32 maxHeight = 0;

        foreach (var mediaProp in mediaProperties)
        {
            VideoEncodingProperties videoProp = mediaProp as VideoEncodingProperties;
            Debug.WriteLine($"VideoProp : {videoProp.Type}:{videoProp.Subtype} {videoProp.Width}x{videoProp.Height}");
            if(videoProp.Subtype == "ARGB32" || videoProp.Subtype == "L8" || videoProp.Subtype == "D16" || videoProp.Subtype == "D8" || videoProp.Subtype == "L16" || videoProp.Subtype == "RGB24")
            { 
                if(maxHeight < videoProp.Height)
                { 
                    videoProfile = videoProp;
                    maxHeight = videoProp.Height;
                }
            }
        }

        if (videoProfile == null)
        {
            Debug.WriteLine("No video profile found...");
            await Task.FromResult<Windows.Foundation.IAsyncAction>(null);
        }

        else
        {
            Debug.WriteLine($"Starting to preview {m_mediaInfo.DeviceInformation.Name} : {m_mediaInfo.DeviceInformation.Id} at {videoProfile.Width}x{videoProfile.Height}: {videoProfile.Subtype}");

            //Create the video encoding
            MediaEncodingProfile profile = new MediaEncodingProfile();
            profile.Video = videoProfile;
            profile.Audio = null;

            //Create and start preview in the MediaSink
            Debug.WriteLine(m_mediaInfo.DeviceInformation.Name);
            m_mediaSink = new HDMediaSinkProxy();
            IMediaExtension ext = await m_mediaSink.InitializeAsync(clbk, profile.Video);
            await m_mediaCapture.StartPreviewToCustomSinkAsync(profile, ext);
        }

        Debug.WriteLine("End of Create media capture async");
    }

Как вы, ребята, видите, я снимаю ЧЕТЫРЕ режима для данного кадра камеры (одна глубина одна ИК-камера и две неизвестные камеры), когда мне нужны только значения глубины в этом кадре. С HoloLens1 я смог получить только камеру глубины с таким же кодом, не имея всех оставшихся изображений, которые, вероятно, будет трудно проанализировать (поскольку я не нашел метаданных, помогающих мне обрезать изображение…) , Я хочу по возможности избежать жесткого кодирования числовых значений c.

Ребята, знаете ли вы, как автоматически извлечь верхнее изображение?

Спасибо!

1 Ответ

0 голосов
/ 01 февраля 2020

Согласно документации, вы можете Установить предпочтительный формат для источника кадра

var colorFrameSource = mediaCapture.FrameSources[colorSourceInfo.Id];
var preferredFormat = colorFrameSource.SupportedFormats.Where(format =>
{
    return format.VideoFormat.Width >= 1080
    && format.Subtype == MediaEncodingSubtypes.Argb32;

}).FirstOrDefault();

if (preferredFormat == null)
{
    // Our desired format is not supported
    return;
}

await colorFrameSource.SetFormatAsync(preferredFormat);

Вам необходимо изменить значения, чтобы получить Глубину.

MediaFrameSource.SetFormatAsyn c

Этот метод является альтернативой MediaCapture.SetEncodingPropertiesAsyn c, но в отличие от SetEncodingPropertiesAsyn c, этот метод можно использовать с любым потоком, а не только цветная камера для предварительного просмотра, записи и захвата фотографий.

...