2016-09-07 232 views
3

當我試圖從文件讀取圖像時,加載後Mat.Data數組一直爲空。但是當我在調試過程中查看Mat對象時,有一個字節數組,其中包含來自圖像的所有數據。EmguCV - Mat.Data數組在加載圖像後始終爲空

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

你知道爲什麼嗎?

回答

0

我認識到這個問題是超級老,但我碰到同樣的問題,我懷疑答案在於Emgu wiki。具體做法是:

訪問像素從墊

不同於圖像<,>類,其中存儲器是預分配的和固定的,墊的存儲器可以自動打開CV函數調用重新分配。我們不能>預先分配託管內存,並假定在Mat對象的整個生命週期中都使用相同的內存。因此,Mat類不包含像Image <>類的Data>屬性,其中可以通過託管數組訪問像素。要訪問Mat的數據,有幾種可能的選擇。 簡單的方法和安全的方式,花費額外的內存副本

第一個選項是使用Mat.ToImage函數將Mat複製到圖像<,>對象。例如

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

像素數據然後可以使用Image <,>。數據屬性來訪問。

您也可以將墊子轉換爲矩陣<>對象。假設墊包含8位數據,

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

請注意,應具有匹配型的墊對象創建矩陣<>。如果Mat包含32位浮點值,則應使用Matrix替換上述代碼中的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 []數組將包含全0,並且不會拋出異常。所以在執行上述操作時要非常小心。

TL; DR:您無法以您希望的方式使用數據對象(至少從版本3.2開始)。您必須將其複製到允許使用Data對象的另一個對象。