ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c#-WinRT从视频流中提取帧

2019-11-20 01:07:42  阅读:307  来源: 互联网

标签:windows-runtime windows-8-1 c


我使用内置摄像头解码条形码,我使用capElement.Source.CapturePhotoToStreamAsync来从预览中捕获照片.它可以正常工作,但是暂时冻结了该应用程序,感觉非常笨拙且有故障.

因此,我希望在后台进行此操作,同时至少在处理照片时保留响应式UI.

到目前为止,我想出了这个来捕获视频流:

 private async void ScanInBackground()
        {
            bool failedScan = true;

            var stream = new InMemoryRandomAccessStream();

            await  capElement.Source.StartRecordToStreamAsync(MediaEncodingProfile.CreateWmv(VideoEncodingQuality.HD1080p), stream);

            while(failedScan)
            {
                Byte[] bytes = await GetBytesFromStream(stream);
                //How to split the bytes into frames?

                Task.Delay(50);
            }

            Dispatcher.RunAsync(CoreDispatcherPriority.Low,() => StopCap()); 
        }

以及从流中获取字节的方法:

public static async Task<byte[]> GetBytesFromStream(IRandomAccessStream randomStream)
        {
            var reader = new DataReader(randomStream.GetInputStreamAt(0));
            var bytes = new byte[randomStream.Size];
            try
            {
                await reader.LoadAsync((uint)randomStream.Size); reader.ReadBytes(bytes);
            }
            catch(Exception ex)
            {
                Logger.LogExceptionAsync(ex, "GetBytesFromStream");
            }
            return bytes;
        }

从ScanInBackground上的评论中,您可以看到我不知道如何将流分割成照片/帧.

解决方法:

尽管它们是针对Windows 10的,但在Microsoft github页面上有一个相关的示例.您可能有兴趣迁移项目以获取此功能.

GetPreviewFrame:此示例将捕获预览框架,而不是完整的照片.具有预览框后,便可以读取和编辑其上的像素.

这是相关的部分:

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;
                }
            }
        }
    }
}

并在您的课外声明:

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

当然,您的项目必须允许不安全的代码才能使所有这些工作.

仔细查看示例以了解如何获取所有详细信息.或者,要进行演练,您可以从最近的// build /会议中观看camera session,其中包括一些摄像机样本的演练.

标签:windows-runtime,windows-8-1,c
来源: https://codeday.me/bug/20191120/2040334.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有