我在Android和優化方面做了很多工作(我寫了一個視頻處理應用程序,處理4ms的幀),所以我希望我會給你一些相關的答案。
OpenCV中的C和C++接口沒有太大的區別。有些代碼是用C編寫的,有一個C++包裝器,還有一些反之亦然。兩者之間的任何顯着差異(如Shervin Emami衡量)都是迴歸,錯誤修復或質量改進。你應該堅持最新的OpenCV版本。
爲什麼不重寫?
你會花很多時間,你可以用得更好。 C接口很麻煩,引入錯誤或內存泄漏的機會很高。在我看來,你應該避免它。
建議優化
A.開啓優化。
編譯器優化和缺少調試斷言都可以使您的運行時間發生重大變化。
B.配置您的應用。
首先在計算機上執行它,因爲它更容易。使用visual studio profiler來識別慢速部分。優化它們。永遠不要優化,因爲你覺得很慢,而是因爲你測量它。從最慢的功能開始,儘可能優化,然後慢一點。衡量你的改變,確保它確實更快。
C.專注於算法。
更快的算法可以提高數量級(100x)的性能。一個C++技巧會給你兩倍的性能提升。
經典技術:
調整大小您的視頻幀要小一些。通常,您可以從200x300px圖像中提取信息,而不是1024x768。第一個地區的面積要小10倍。
使用更簡單的操作,而不是複雜的操作。使用整數而不是浮點數。千萬不要在矩陣中使用double
或者執行數千次的for
循環。
儘可能少的計算。您是否可以僅在圖像的特定區域跟蹤對象,而不是全部處理所有幀?您可以對非常小的圖像進行粗略/近似檢測,然後在全幀中以ROI對其進行優化?
D.使用C,其中它的事項
在循環中,它可能是有意義的用C的風格,而不是C++。指向數據矩陣或浮點數組的指針比mat.at或std :: vector <>快得多。通常瓶頸是嵌套循環。關注它。在所有地方替換矢量並且代碼化代碼是沒有意義的。
E.避免隱性成本
一些OpenCV函數轉換數據提高一倍,處理它,然後再轉換回輸入格式。小心他們,他們會殺死移動設備上的性能。示例:翹曲,縮放,類型轉換。此外,色彩空間轉換被認爲是懶惰的。希望直接從原生YUV獲取灰度。
F.使用矢量
ARM處理器實現量化與一個叫NEON技術。學會使用它。它是強大的!
一個小例子:
float* a, *b, *c;
// init a and b to 1000001 elements
for(int i=0;i<1000001;i++)
c[i] = a[i]*b[i];
可以如下重寫。它更詳細,但更快。
float* a, *b, *c;
// init a and b to 1000001 elements
float32x4_t _a, _b, _c;
int i;
for(i=0;i<1000001;i+=4)
{
a_ = vld1q_f32(&a[i]); // load 4 floats from a in a NEON register
b_ = vld1q_f32(&b[i]);
c_ = vmulq_f32(a_, b_); // perform 4 float multiplies in parrallel
vst1q_f32(&c[i], c_); // store the four results in c
}
// the vector size is not always multiple of 4 or 8 or 16.
// Process the remaining elements
for(;i<1000001;i++)
c[i] = a[i]*b[i];
較真say必須在彙編寫的,但對於一個普通的程序員,這是一個有點嚇人。我使用gcc intrinsics獲得了很好的結果,就像上面的例子。
另一種快速啓動的方法是在OpenCV中將手動編碼的SSE優化代碼轉化爲NEON。 SSE是Intel處理器中的NEON等價物,許多OpenCV功能都使用它,如here。這是uchar矩陣(常規圖像格式)的圖像過濾代碼。你不應該盲目地一個接一個地轉換指令,而應該以此爲例。
您可以在this blog以及後面的文章中閱讀更多關於NEON的內容。
G.注重形象捕獲
它可以是一個移動設備上慢得出奇。優化它是設備和操作系統特定的。
我對android並不熟悉,但使用OpenCV的C接口不會給你任何顯着的性能提升,因爲它仍然使用相同的基本代碼。 – Mohammad 2012-07-07 15:47:41
我已經添加了一些更多的信息給我的答案,希望你會發現它有用。 – Sam 2012-07-07 19:45:50