Access preview frame from MediaCapture

前端 未结 1 1706
一个人的身影
一个人的身影 2020-12-29 00:30

I would like to grab the preview frames that are displayed inside my CaptureElement xaml element. The source of my CaptureElement is

相关标签:
1条回答
  • 2020-12-29 01:06

    There is a sample on the Microsoft github page that is relevant, although they target Windows 10. You may be interested in migrating your project to get this functionality.

    GetPreviewFrame: This sample will capture preview frames as opposed to full-blown photos. Once it has a preview frame, it can edit the pixels on it.

    Here is the relevant part:

    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;
    
            // Add a simple green filter effect to the SoftwareBitmap
            EditPixels(previewFrame);
        }
    }
    
    private unsafe void EditPixels(SoftwareBitmap bitmap)
    {
        // Effect is hard-coded to operate on BGRA8 format only
        if (bitmap.BitmapPixelFormat == BitmapPixelFormat.Bgra8)
        {
            // In BGRA8 format, each pixel is defined by 4 bytes
            const int BYTES_PER_PIXEL = 4;
    
            using (var buffer = bitmap.LockBuffer(BitmapBufferAccessMode.ReadWrite))
            using (var reference = buffer.CreateReference())
            {
                // Get a pointer to the pixel buffer
                byte* data;
                uint capacity;
                ((IMemoryBufferByteAccess)reference).GetBuffer(out data, out capacity);
    
                // Get information about the BitmapBuffer
                var desc = buffer.GetPlaneDescription(0);
    
                // Iterate over all pixels
                for (uint row = 0; row < desc.Height; row++)
                {
                    for (uint col = 0; col < desc.Width; col++)
                    {
                        // Index of the current pixel in the buffer (defined by the next 4 bytes, BGRA8)
                        var currPixel = desc.StartIndex + desc.Stride * row + BYTES_PER_PIXEL * col;
    
                        // Read the current pixel information into b,g,r channels (leave out alpha channel)
                        var b = data[currPixel + 0]; // Blue
                        var g = data[currPixel + 1]; // Green
                        var r = data[currPixel + 2]; // Red
    
                        // Boost the green channel, leave the other two untouched
                        data[currPixel + 0] = b;
                        data[currPixel + 1] = (byte)Math.Min(g + 80, 255);
                        data[currPixel + 2] = r;
                    }
                }
            }
        }
    }
    

    And declare this outside your class:

    [ComImport]
    [Guid("5b0d3235-4dba-4d44-865e-8f1d0e4fd04d")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    unsafe interface IMemoryBufferByteAccess
    {
        void GetBuffer(out byte* buffer, out uint capacity);
    }
    

    And of course, your project will have to allow unsafe code for all of this to work.

    Have a closer look at the sample to see how to get all the details. Or, to have a walkthrough, you can watch the camera session from the recent //build/ conference, which includes a little bit of a walkthrough through some camera samples.

    0 讨论(0)
提交回复
热议问题