2016-10-11 106 views
0

我的目標是用OpenCV函數(如NL表示去噪)來增強我的預先存在的圖像處理流水線(用Halide編寫)。 OpenCV函數將無法使用Halide的調度功能,因此我的計劃是在每個OpenCV階段之前實現每個Halide Func。剩下的問題是如何從Halide Image(Func實現的結果)最佳轉換爲OpenCV Mat(作爲OpenCV函數的輸入)以及完成時從OpenCV Mat到Halide Image。我的Halide圖像是浮點類型,有3個通道。如何將OpenCV Mat轉換爲Halide Image並返回?

對此的一個明顯的解決方案是編寫將數據從一種數據類型複製到另一種數據類型的函數,但這會讓我覺得很浪費。不僅需要花費寶貴的時間來複制數據,還會浪費內存,因爲圖像將作爲兩種不同的數據類型存儲。有沒有辦法使用指針或數據緩衝區來簡單地以新格式重新打包圖像數據?希望這個過程是可逆的,所以我可以從Halide轉到OpenCV,然後在OpenCV函數返回到Halide之後。

回答

0

是的,你可以避免複製數據。我看到兩種可能的方法:自己分配內存並在OpenCV Mat實例和Halide buffer_t結構中引用該內存;或者讓OpenCV的Mat類分配內存並在buffer_t結構中引用該內存。

對於第一種方法,可以使用一個墊構造函數的數據指示字:

float* data = new float[3 * width * height]; 
cv::Mat image(height, width, CV_32FC3, data, AUTO_STEP); 

對於第二種方法,可以使用通常的構造或墊::創建方法:

cv::Mat image(height, width, CV_32FC3); 

無論哪種方式,你可以使用類似下面的代碼來包裝內存在鹵化物buffer_t結構:

buffer_t buffer; 
memset(&buffer, 0, sizeof(buffer)); 
buffer.host = image.data; 
buffer.elem_size = image.elemSize1(); 
buffer.extent[0] = image.cols; 
buffer.extent[1] = image.rows; 
buffer.extent[2] = image.channels(); 
buffer.stride[0] = image.step1(1); 
buffer.stride[1] = image.step1(0); 
buffer.stride[2] = 1; 

現在,您應該可以使用OpenCV和Halide功能在相同的存儲器上運行。

+0

非常感謝您的回答Eric。我將代碼設置爲按照您所描述的方式工作,並且在大多數情況下,它適用於OpenCV和Halide。 一個奇怪的問題是,當我從buffer_t製作圖像時:Image input(buffer);輸出看起來不正確。 – Kantthpel

+0

對不起,看起來我們不能編輯評論。我的意思是說,當我保存從緩衝區創建的圖像時,輸出看起來不正確。但是,當通過任何Func傳遞時,數據看起來被正確存儲,因爲將不執行計算的Func的輸出保存在正確的輸出中。 看來,通過Func傳遞圖像的行爲正在糾正從緩衝區創建的圖像中的錯誤 – Kantthpel

+0

對於奇怪的行爲的替代方案可能是save_image鹵化物函數無法正確解析在緩衝。我認爲這種情況的原因是,當輸入數據是平面的時候,圖像在通過空白Func之前和之後看起來都是正確的。但是,當輸入數據交錯時(OpenCV的默認值),那麼只有通過空白Func傳遞的圖像看起來是正確的。 – Kantthpel