2014-04-23 43 views
2

內存管理對於圖像類是至關重要的。在opencv中,映像類是cv::Mat,它具有精巧的內存管理方案。假設我已經有我自己的形象類SelfImageOpencv Mat內存管理

class SelfImage 
{ 
    public: 
    int width_; 
    int height_; 
    unsigned char *pPixel_;  
}; 

在開始的時候,我會把所有的圖像像素內容,這個類:

SelfImage myImage; 
myImage.width_ = 300; 
myImage.height_ = 200; 
myImage.pPixel_ = new [300*200]; 
for(int i=0; i<300*200; i++) 
     myImage.pPixel_[i] = i%200; 

然後我的問題是如何改變這個類在一個非常有效的方式cv::Mat,一個解決方案,我擁有的是:

cv::Mat mat; 
    mat.create(myImage.height_, myImage.width_, CV_8UC1); 
    mat.data = myImage.pPixel_; 

我不知道這是否是一個很好的解決方案。如果cv::Mat::create函數也會分配內存,那麼上面的代碼就有內存泄漏的危險。有任何想法嗎?

編輯 我必須說清楚,這將是很好,如果我可以使用cv::Mat::create方法,但共享SelfImage class.The原因的內存是一個函數定義爲perfom圖像類轉換作業void TransImageType(const SelfImage &geo_img, cv::Mat &mat);

回答

5

cv::Mathas a constructor在那裏你可以指定用戶數據:

Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP) 

文檔說以下有關data說法:

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

+0

我必須說清楚,如果我可以使用'cv :: Mat :: create'方法但是與'SelfImage'類共享內存。 – feelfree

+0

我不認爲這是可能的...看到[相關的問題](http://stackoverflow.com/questions/22511747/how-do-i-pass-ownership-of-pixel-data-to-cvmat) 。爲什麼你不能使用該構造函數? – AldurDisciple

+0

謝謝,原因是一個函數被定義爲執行圖像類的轉換作業void TransImageType(const SelfImage&geo_img,cv :: Mat &mat); – feelfree

1

Mat::create()分配數據(total()*elemSize()字節)並初始化分配的數據的1內部參考計數器,(當Mat已經存在並且具有在create()方法中指定的相同的大小/類型除外)。

是的,您的代碼會產生內存泄漏,因爲當您移動Mat::data指針時,由Mat::create()分配的數據會丟失。

正確的做法應該是(在我看來)通過使用memcpymyImage.pPixel_mat.data(在致電create()後)。這看起來效率不高,但好的一面是,析構函數將處理數據的重新分配。

1

您可以簡單地使用

Mat mat = Mat(myImage.height_, myImage.width_, CV_8UC1, myImage.pPixel_); 

這樣,沒有數據被複制。當然,作爲價格,你應該注意釋放內存。

從它doc

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

+0

我必須說清楚,如果我可以使用'cv :: Mat :: create'方法但是與'SelfImage'類共享內存將會很好。 – feelfree

+0

@feelfree如果是這樣,你正在做正確的方法。 :P – herohuyongtao

+0

謝謝,我正在努力解決它:) – feelfree

1

這取決於您是否要複製數據。

從您的建議,似乎你想分享數據。在這種情況下,這是最好的解決辦法:

cv::Mat mat(myImage.height_, myImage.width_, CV_8U, myImage.pPixel_); 

mat不會釋放內存,當它被釋放,你就必須這樣做。

如果要複製數據,請創建一個正常的cv::Mat,稍後再做std::copy(或memcpy,如@KeillRandor建議的那樣)。

+0

感謝您的評論,但在這裏我不能直接使用cv :: Mat mat(myImage.height_,myImage.width_ ,CV_8U,myImage.pPixel_)。 – feelfree