2016-09-07 5 views
3

Когда я пытаюсь прочитать изображение из файла, то после загрузки массива Mat.Data всегда ноль. Но когда я смотрю на объект Mat во время отладки, есть массив байтов, в котором находятся все данные из изображения.EmguCV - массив Mat.Data всегда равен нулю после загрузки изображения

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

У вас есть идеи, почему?

ответ

0

Я признаю, что этот вопрос очень старый, но я попал в ту же проблему, и я подозреваю, что ответ лежит в Emgu wiki. В частности:

Доступ пикселы из Мат

В отличие от изображения <,> класс, где память заранее распределены и фиксирована, память Мат может быть автоматически перераспределены вызовами функций Open CV. Мы не можем> предварительно распределить управляемую память и предположить, что одна и та же память используется через время жизни объекта Mat. В результате класс Mat не содержит свойства Data>, такого как Image <,> class, где пиксели могут быть доступны через управляемый массив. Чтобы получить доступ к данным Mat, существует несколько возможных вариантов. Легкий способ и безопасный способ, который стоит дополнительной копии памяти

Первый вариант - скопировать объект Mat в изображение <,> с использованием функции Mat.ToImage. например

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

пиксельные данные могут быть доступны с помощью Image <,>. Данные объекта.

Вы также можете преобразовать матрицу в матрицу <> объект. Предполагая, что Mat содержит 8-битные данные,

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

Обратите внимание, что вы должны создать матрицу <> с типом соответствия к объекту Mat. Если Mat содержит 32-битное значение с плавающей запятой, вы должны заменить Matrix в приведенном выше коде матрицей. После этого данные пикселов можно получить, используя свойство Matrix <> .Data. Самый быстрый способ без копирования памяти. Будьте осторожны!

Второй вариант немного сложный, но обеспечит наилучшую производительность. Обычно вам требуется знать размер объекта Mat перед его созданием. Таким образом, вы можете выделить управляемый массив данных и создать объект Mat, заставив его использовать закрепленную управляемую память. например

//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 [] будет содержать все 0s, и никакое исключение не будет выбрано. Поэтому будьте очень осторожны при выполнении вышеуказанных операций.

TL; DR: Вы не можете использовать объект Data так, как вы надеетесь (по крайней мере, начиная с версии 3.2). Вы должны скопировать его на другой объект, который позволяет использовать объект Data.