EmguCV - 图像加载后,Mat.Data数组始终为空

时间:2016-09-07 13:46:09

标签: opencv emgucv

当我尝试从文件中读取图像时,在加载Mat.Data数组之后总是为空。但是当我在调试期间查看Mat对象时,存在字节数组,其中包含来自图像的所有数据。

Mat image1 = CvInvoke.Imread("minion.bmp", Emgu.CV.CvEnum.LoadImageType.AnyDepth);

你知道为什么吗?

1 个答案:

答案 0 :(得分:0)

我认识到这个问题已经超级老了,但我遇到了同样的问题,我怀疑答案在于Emgu wiki。具体做法是:

  

从Mat

访问像素      

与Image<,>不同类,其中内存是预先分配和修复的,Mat的内存可以通过Open CV函数调用自动重新分配。我们不能>预分配管理内存并假设在Mat对象的生命周期内使用相同的内存。因此,Mat类不包含数据>属性如Image<,> class,可以通过托管数组访问像素。要访问Mat的数据,有几种可能的选择。   花费额外内存副本的简单方法和安全方法

     

第一个选项是将Mat复制到Image<,>使用Mat.ToImage函数的对象。 e.g。

     

Image<Bgr, Byte> img = mat.ToImage<Bgr, Byte>();

     

然后可以使用Image&lt;,&gt; .Data属性访问像素数据。

     

您还可以将Mat转换为矩阵&lt;&gt;宾语。假设Mat包含8位数据,

Matrix<Byte> matrix = new Matrix<Byte>(mat.Rows, mat.Cols, mat.NumberOfChannels);
mat.CopyTo(matrix);
     

请注意,您应该创建Matrix&lt;&gt;与Mat对象匹配的类型。如果Mat包含32位浮点值,则应将上述代码中的Matrix替换为Matrix。然后可以使用Matrix&lt;&gt; .Data属性访问像素数据。   无需内存复制的最快方法。小心!!!

     

第二种选择有点棘手,但会提供最佳性能。这通常需要您在创建Mat对象之前知道它的大小。因此,您可以分配托管数据阵列,并通过强制它使用固定的托管内存来创建Mat对象。 e.g。

//load your 3 channel bgr image here
Mat m1 = ...;

//3 channel bgr image data, if it is single channel, the size should be m1.Width * m1.Height

byte[] data = new byte[m1.Width * m1.Height * 3];`
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);`
using (Mat m2 = new Mat(m1.Size, DepthType.Cv8U, 3, handle.AddrOfPinnedObject(), m1.Width * 3))`
    CvInvoke.BitwiseNot(m1, m2);`
handle.Free();
     

此时数据阵列包含反转图像的像素数据。请注意,如果Mat m2的分配大小错误,data []数组将包含全0,并且不会抛出任何异常。因此在执行上述操作时要非常小心。

TL; DR:您不能以您希望的方式使用Data对象(至少从3.2版本开始)。您必须将其复制到另一个允许使用Data对象的对象。