稀疏矩陣在opencv中的應用(大矩陣運算速度過慢的問題,藉助SparseMat?)
大矩陣相乘的問題
很多演算法在執行的過程中產生的大矩陣往往包含很多0元素,我們下面的內容也是主要針對這類矩陣展開的。所以這個問題換一個說法就是 稀疏矩陣在opencv中的應用
可以看出,opencv確實支援稀疏矩陣,也就是SparseMat
,用法和常規的 Mat
類似,但是 SparseMat
和 Mat
的底層實現是完全不一樣的,前者採用的是hash表,後者就是常規的矩陣儲存。
cv::SparseMat uses a hash table to store just the nonzero elements. That hash table is maintained automatically
, so when the number of (nonzero) elements in the array becomes too large for efficient lookup, the table grows automatically.cv::SparseMat is a hash table. Looking up objects in a hash table requires two steps: first, computing the hash key (in this case, from the indices), and second, searching a list associated with that key. Normally, that list will be short (ideally only one element), so the primary computational cost in a lookup is the computation of the hash key.
If this key has already been computed (as with cv::SparseMat::hash(), which will be covered next), then time can be saved by not recomputing it. In the case of cv::SparseMat::ptr(), if the argument hashval is left with its default argument of NULL, the hash key will be computed. If, however, a key is provided, it will be used.
那麼問題來了,SparseMat
是不能隨意支援跟 Mat
一樣的操作的(底層實現的差別),所以,真實情況是,opencv的 SparseMat
支援的操作非常有限,比如並不支援四則運算,這就很尷尬了…
解決方案一
自己藉助
SparseMat
實現矩陣四則運算操作,比如矩陣相乘,因為opencv至少提供了稀疏矩陣的元素訪問API。但怎麼說呢,自己實現的話,效率是一個問題,還有就是難道要實現所有的矩陣運算嗎?如果需要複雜的運算,比如求解線性方程組,就比較費勁了。解決方案二
藉助第三方庫,比如
eigen
好訊息是opencv的底層矩陣運算就是使用的eigen庫,所以opencv和eigen可以很方便的連通。opencv甚至給了兩者矩陣物件相互轉換的介面:cv2eigen和eigen2cv
eigen庫的使用簡介
sparse = dense.sparseView(epsilon,reference);
dMat = MatrixXd(spMat);
所以大型矩陣相乘或者求解執行緒方程組都可以使用稀疏矩陣來做,速度會快很多!
但需要注意的是,演算法的速度問題從來都不是一個稀疏矩陣可以解決的,演算法本身的實現或者優化是最關鍵的模組!