2014-03-19 64 views
2

我正在創建一個cv :: Mat,並傳遞了我已經在外部分配的像素數據。如何將像素數據的所有權轉交給cv :: Mat

cv::Mat myMatrix(vImageResult.height, 
       vImageResult.width, 
       CV_8UC1, 
       vImageResult.data); 

我希望cv :: Mat獲得字節的所有權(即創建一個refCount並在達到零時釋放字節)。然而documentation

矩陣構造函數採取數據和步驟參數不分配矩陣數據。相反,他們只是初始化指向指定數據的矩陣頭,這意味着沒有數據被複制。此操作非常高效,可用於使用OpenCV函數處理外部數據。 外部數據不會自動釋放,所以您應該照顧它。

  • 如果我立即釋放潛在的vImageResult.data,則我會得到一個壞的接入碰撞的地方下了線。
  • 如果我沒有釋放底層的vImageResult.data,那麼數據會韭菜。

有沒有辦法通過所有權?

+0

剛做'myMatrix = vImageResult'有什麼問題? – AldurDisciple

+0

@AldurDisciple vImageResult可能不是cv :: Mat。這應該是「外部分配」的意思,這是我在寫答案時所設想的。 – anderas

+3

我不認爲你可以這樣做,因爲Mat不知道你如何分配內存(malloc,new等),因此不知道如何釋放它。 – bitwise

回答

3

你不能。

cv :: Mat不知道如何分配內存(malloc,new等),因此不知道如何釋放它。

如果您自己分配數據,則始終可以撥打cv::Mat::create(...)來分配所需的內存,然後將指針myMatrix.data傳遞給您用於加載數據的任何函數。

如果您指的是通過視頻捕捉流或外部庫向您提供的預分配內存,那麼您運氣不好。

安德烈亞斯的解決方案將工作,但如果經常使用可能會變慢。

妥協也許是你自己的類型來包裝cv::Mat

struct MyMat 
{ 
    cv::Mat mat; 
    MyMat(int width, int height, int format, char *data) 
     : mat(height, width, format, data){} 
    ~MyMat() { delete [] mat.data; } 
}; 

注:這是故意要設法子類品種::墊。它沒有虛擬析構函數。

4

一個選項是使用Mat::clone()將數據複製到一個新的矩陣,該矩陣執行數據的深層副本。新矩陣將擁有克隆數據的所有權。

例如:

// create temporary matrix that holds the external/old data 
cv::Mat tmp(vImageResult.height, 
      vImageResult.width, 
      CV_8UC1, 
      vImageResult.data); 
cv::Mat myMatrix = tmp.clone(); // myMatrix now has ownership of a clone of the data. 
+1

和原始數據可以在複製後立即釋放。這也是我的建議,儘管嚴格來說這不是問題的答案:D – Micka

+1

正確(對兩點)。據我在文檔中看到的,沒有辦法通過所有權,所以這個選項將最接近OP想要的。 – anderas

+0

@anderas在假設'vImageResult'不是'cv :: Mat'的時候你必須是正確的,但是也許你應該添加一些關於如何使用clone()來傳遞所有權的細節。 – AldurDisciple