在C#中读取ROS CompressedImage数据字节数组

时间:2017-02-14 16:23:17

标签: c# opencv bitmap emgucv bitmapimage

我想访问16UC1格式的png图像的每个像素值的值,我将其作为byte []接收。

我对C#中的图像处理非常陌生,我现在已经陷入这个问题了几天。

我可以使用"典型的" bgr8格式的jpg / png字节数组只需:

private static Bitmap getBitmap(byte[] array)
{
return new Bitmap(new MemoryStream(array));
}

我为16UC1格式尝试了很多东西。我得到的最远的是:

private Bitmap getBitmap(byte[] array)
{
    var bitmap = new Bitmap(640,480,PixelFormat.Format16bppRgb555);

    var bitmapData = bitmap.LockBits(new Rectangle(0, 0, 640, 480), ImageLockMode.WriteOnly, PixelFormat.Format16bppRgb555);
    System.Runtime.InteropServices.Marshal.Copy(bitmapData.Scan0, array, 0, array.Length);
    bitmap.UnlockBits(bitmapData);

    return bitmap;
}

这至少会返回一个位图,尽管它完全是黑色的。 尝试使用PixelFormat.Format16bppGrayScale代替PixelFormat.Format16bppRgb555会在GDI +"中给出一个"一般错误。

当通过例如文件将字节数组写入文件时由

File.WriteAllBytes(filename, array);

虽然Windows照片查看器失败,但我可以看到像IrfanView这样的图像查看器的图像。

不需要将文件作为位图读取。出于性能原因,我想避免文件操作。我只是想访问该图像的每个xy像素。

更新: 我开始使用Emgu.CV并应用下面提出的Dan建议的imdecode。

private Bitmap getCompressedDepthBitmap(byte[] data)
{
    Mat result = new Mat(new Size(640, 480), DepthType.Cv16U, 1);
    CvInvoke.Imdecode(data,LoadImageType.AnyDepth, result);
    return result.Bitmap;           
}

这再次给了我一个黑色的图像。 (通过WriteAllBytes保存字节数组,我看到有用的内容。)我也试过

Image<Gray, float> image = result.ToImage<Gray, float>();
image.Save(Path.Combine(localPath, "image.png"));

这也给了我一个黑色的图像。 我现在计划以某种方式将Mat正常化,也许这会有所帮助...

感谢您的关注和支持!

1 个答案:

答案 0 :(得分:0)

经过几个小时的浪费工作时间和绝望,我终于找到了解决方案......

我在上面的描述中遗漏的一件重要事情是图像数据byte []来自ROS sensor_msgs / CompressedImage.msg。

应该包含png数据的数据字节数组有时以12byte头开头;看似只有数据是(1通道)压缩的深度图像。我意外地发现了这个信息here

删除这些令人敬畏的令人讨厌的12个字节并像往常一样继续工作:

var bitmap = new Bitmap(new MemoryStream(dataSkip(12).ToArray()));