从WriteableBitmap转换为Mat然后在带有CvInvoke.Imshow的窗口中显示它?

时间:2017-02-01 14:28:00

标签: c# kinect emgucv

我从Kinect V2相机中取出红外帧。这些框架以WritableBitmap的形式出现,所以我尝试使用我制作的代码进行转换:

public Mat WritableBitmapToMat(WriteableBitmap writeBmp)
{
    Bitmap bmp;
    using (MemoryStream outStream = new MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create((BitmapSource)writeBmp));
        enc.Save(outStream);
        bmp = new Bitmap(outStream);
    }

    Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);

    BitmapData bmpData = bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);

    IntPtr data = bmpData.Scan0;

    int step = bmpData.Stride;

    Mat mat = new Mat(bmp.Height, bmp.Width, Emgu.CV.CvEnum.DepthType.Cv32F, 4, data, step);

    bmp.UnlockBits(bmpData);

    return mat;
}

我不知道转换是否有问题,但是当我尝试使用此代码在窗口中显示图像时:

CvInvoke.Imshow("window showing a picture", infraredMat);

我最终得到一个如下所示的异常:

异常:抛出异常:Emgu.CV.World.dll中的“System.AccessViolationException”(“试图读取或写入受保护的内存。这通常表示其他内存已损坏。”)。

我还想提一下我使用的是EmguCV 3.1和Kinect SDK 2.0

提前感谢我获得的任何帮助。

3 个答案:

答案 0 :(得分:1)

如果您查看Kinect 2.0 SDK中的InfraredBasics-WPF示例,则会将IR图像从ushort方法提取到FrameReference.AcquireFrame()向量中。然后,您可以使用IntPtr infraredBuffer.UnderlyingBuffer访问帧数据(以不安全的方法)来获取1-D向量。如果需要,您可以稍后使用标准2xfor循环将1-D转换为2-D矩阵。

这样您就不必访问`BitmapEncoder中的数据了。另外,因为它是SDK中的标准示例,所以我认为这是获取IR帧的推荐方法。此外,该示例还包含用于显示IR图像的方法;除非你有特定的方法/理由使用你的方式。

答案 1 :(得分:0)

使用以下代码可以很容易地将C#中的位图转换为EMGUCV的Mat:

Bitmap bmp = new Bitmap("FilePath");//Declare a Bitmap Object
Image<Bgr, Byte> bmp_I = new Image<Bgr, byte>(bmp);//Creating an Image object in EMGUCV which can read Bitmap object.
Mat converted_mat = bmp_I.Mat;//Convert Image object into Mat 

答案 2 :(得分:0)

我使用这种方法取得了很大的成功:

    public static Mat ToMat(BitmapSource source)
    {
        if (source.Format == PixelFormats.Bgra32)
        {
            Mat result = new Mat();
            result.Create(source.PixelHeight, source.PixelWidth, DepthType.Cv8U, 4);
            source.CopyPixels(Int32Rect.Empty, result.DataPointer, result.Step * result.Rows, result.Step);
            return result;
        }
        else if (source.Format == PixelFormats.Bgr24)
        {
            Mat result = new Mat();
            result.Create(source.PixelHeight, source.PixelWidth, DepthType.Cv8U, 3);
            source.CopyPixels(Int32Rect.Empty, result.DataPointer, result.Step * result.Rows, result.Step);
            return result;
        }
        else if (source.Format == PixelFormats.Pbgra32)
        {
            Mat result = new Mat();
            result.Create(source.PixelHeight, source.PixelWidth, DepthType.Cv8U, 4);
            source.CopyPixels(Int32Rect.Empty, result.DataPointer, result.Step * result.Rows, result.Step);
            return result;
        }
        else
        {
            throw new Exception(String.Format("Conversion from BitmapSource of format {0} is not supported.", source.Format));
        }
    }

您可以根据需要调整此项。我不确定ImShow是否会处理32位浮点数的BitMap。通常,位图充满了字节。我可能是错的,但我从来没有试图得到任何东西,以显示浮动。

道格