C# 将字节[]转换为Emgu/OpenCV图像

C# 将字节[]转换为Emgu/OpenCV图像,c#,opencv,kinect,emgucv,C#,Opencv,Kinect,Emgucv,我有一个表示灰度图像的字节数组,我想使用Emgu包装器在C#中与openCV一起使用。我正在试图找出如何将其转换为Emu.CV.Image,而不首先将其转换为System.Drawing.Bitmap 到目前为止,Image的构造函数似乎很有希望。看起来它需要像素行、列,然后是包含我的数据的数组来构建图像。但是,它希望它们采用一种奇怪的格式,我正在努力解决如何正确构造TDepth[,]数据参数的问题 以下是我目前掌握的情况: // This gets initialized in the con

我有一个表示灰度图像的字节数组,我想使用Emgu包装器在C#中与openCV一起使用。我正在试图找出如何将其转换为
Emu.CV.Image
,而不首先将其转换为
System.Drawing.Bitmap

到目前为止,
Image
的构造函数似乎很有希望。看起来它需要像素行、列,然后是包含我的数据的数组来构建图像。但是,它希望它们采用一种奇怪的格式,我正在努力解决如何正确构造
TDepth[,]数据
参数的问题

以下是我目前掌握的情况:

// This gets initialized in the constructor and filled in with greyscale image data elsewhere in the code:
byte[] depthPixelData

// Once my depthPixelData is processed, I'm trying to convert it to an Image and this is where I'm having issues
Image<Gray, Byte> depthImage = new Image<Gray, Byte>([depthBitmap.PixelHeight, depthBitmap.pixelWidth, depthPixelData]);
//这将在构造函数中初始化,并在代码的其他地方填充灰度图像数据:
字节[]深度像素数据
//一旦我的depthPixelData被处理,我会尝试将其转换为图像,这就是我遇到的问题
图像深度图像=新图像([depthBitmap.PixelHeight,depthBitmap.pixelWidth,depthPixelData]);
VisualStudio让我明白,仅仅传入一个数组并不能切割它,但我不知道如何使用像素数据构造必要的
TDepth[,,]
对象,以便传入
图像
构造函数


这段代码需要以大约30fps的速度运行,因此我正试图在对象创建、内存分配等方面尽可能提高效率。

就我个人而言,我会按照这些思路做一些事情:

byte[] depthPixelData = ...;

int imageWidth = ...;
int imageHeight = ...;
int channelCount = 1; // grayscale

byte[,,] depthPixelData3d = new byte[imageHeight, imageWidth, channelCount];

for(int line = 0, offset = 0; line < imageHeight; line++)
    for(int column = 0; column < imageWidth; column++, offset++)
        depthPixelData3d[line, column, 0] = depthPixelData[offset];
byte[]depthPixelData=。。。;
int imageWidth=。。。;
int-imageHeight=。。。;
int channelCount=1;//灰度
字节[,]深度像素数据3D=新字节[imageHeight,imageWidth,channelCount];
对于(int line=0,offset=0;line

出于性能考虑,您可能希望:

  • 将其转化为不安全的块(应该是微不足道的)
  • 仅分配字节[,]一次(除非图像大小更改)

Emu.Cv.Image类定义为

public class Image<TColor, TDepth> : CvArray<TDepth>, ...

另一个解决方案是仅使用图像的宽度和高度创建EMGU.CV.Image。然后你可以这样做:

byte[] depthPixelData = new byte[640*480]; // your data

Image<Gray, byte> depthImage = new Image<Gray, byte>(640, 480);

depthImage.Bytes = depthPixelData;
byte[]depthPixelData=新字节[640*480];//你的数据
图像深度图像=新图像(640480);
字节=深度像素数据;

只要宽度和高度正确,并且宽度可以被4整除(Emgu.CV.Image是如何实现的),就应该没有问题。您甚至可以重用Emgu.CV.Image对象,如果不需要保存对象,只需每帧更改字节。

啊,我明白了。因此,无法避免复制数组?您可以尝试类似于
var gcHandle=gcHandle.Alloc(depthPixelData,GCHandleType.pinted)的方法;IntPtr address=gcHandle.addrofPindedObject();图像深度图像=新图像(深度位图.PixelHeight、深度位图.PixelWidth、颜色通道、地址)但在您的情况下,非托管实现可能会更好…这对我来说很好!感谢您的提示,希望有更好的文档说明Emgu的速度和速度(使用
depthImage.Data[x,y]=
写入字节的速度大约比这个慢10倍)。
byte[] depthPixelData = new byte[640*480]; // your data

Image<Gray, byte> depthImage = new Image<Gray, byte>(640, 480);

depthImage.Bytes = depthPixelData;