【问题标题】:How to create a Image or Mat instance from a YUV_420_888 byte array in EmguCV?如何从 EmguCV 中的 YUV_420_888 字节数组创建 Image 或 Mat 实例?
【发布时间】:2021-04-19 10:03:22
【问题描述】:

问题: 我从 android 设备接收 YUV_420_888 图像作为字节缓冲区(简单地连接图像平面缓冲区)。我知道图像的尺寸,我需要将它显示到我的 GUI 上。

我目前所拥有的: 目前我只能使用具有以下功能的灰度 Y 平面:

private BitmapImage GetImageFromBuffer(byte[] imgBuffer)
{
    Image<Gray, byte> emguImg = new Image<Gray, byte>(1280, 720);
    emguImg.Bytes = imgBuffer;

    var img = new BitmapImage();
    using (MemoryStream ms = new MemoryStream(emguImg.ToJpegData()))
    {
        img.BeginInit();
        img.CacheOption = BitmapCacheOption.OnLoad;
        img.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
        img.StreamSource = ms;
        img.EndInit();
    }
    return img;
}

我也测试了类似的代码,使用Image.ToBitmap() 函数并将中间位图复制到内存流中,作为BitmapImage 的源。 无论如何,我想从传入的byte[] 创建一个BitmapSourceBitmapImage(或我可以用来在GUI 上显示的任何类型)。 据我所知,我必须从字节数组创建一个 Mat 实例,将其转换为 RGB,然后将其保存为可显示的格式。

【问题讨论】:

    标签: c# wpf emgucv


    【解决方案1】:

    以下代码似乎可以解决问题:

    private BitmapImage GetImageFromBuffer(byte[] imgBuffer)
    {
        unsafe
        {
            fixed (byte* p = imgBuffer)
            {
                IntPtr ptr = (IntPtr)p;
                Mat yuvMat = new Mat(1080, 1280, Emgu.CV.CvEnum.DepthType.Cv8U, 1, ptr, 1280);
                Mat rgbMat = new Mat();
                CvInvoke.CvtColor(yuvMat, rgbMat, Emgu.CV.CvEnum.ColorConversion.Yuv420Sp2Rgb);
                var img = new BitmapImage();
                using (MemoryStream ms = new MemoryStream())
                {
                    img.BeginInit();
                    rgbMat.Bitmap.Save(ms, ImageFormat.Bmp);
                    img.CacheOption = BitmapCacheOption.OnLoad;
                    img.CreateOptions = BitmapCreateOptions.PreservePixelFormat;
                    img.StreamSource = ms;
                    img.EndInit();
                }
                return img;
            }
        }
    }
    

    也许有人可以确认,如果这是要走的路或评论改进建议。

    【讨论】:

    • 嘿,根据您问题中的代码,您的图像分辨率似乎是 720p,但在您的回答中,您使用 1080 和 1280 作为“行”和“列”。这是基于不同的图像分辨率,还是您为获得这些数字做了一些计算?
    • 抱歉,我找到了答案:显然是将图像宽度乘以 1.5 得到函数中的“1080”值。
    • 没错,这是由于 YUV 图像格式的布局方式 :) 这是一个很好的说明,它说明了为什么需要乘以 1.5:stackoverflow.com/questions/27822017/planar-yuv420-data-layout
    猜你喜欢
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-03
    • 2010-09-26
    • 2011-09-28
    • 2011-12-22
    相关资源
    最近更新 更多