eigen稀疏矩陣拼接(基於塊操作的二維拼接)的思考
eigen稀疏矩陣拼接(塊操作)
關於稀疏矩陣的塊操作:參考官方連結
However, for performance reasons, writing to a sub-sparse-matrix is much more limited, and currently only contiguous sets of columns (resp. rows) of a column-major (resp. row-major) SparseMatrix are writable. Moreover, this information has to be known at compile-time, leaving out methods such as block(…) and corner*(…). The available API for write-access to a SparseMatrix are summarized below:
上面規則對應的示例:
SparseMatrix<double,ColMajor> sm1;
sm1.col(j) = ...;
sm1.leftCols(ncols) = ...;
sm1.middleCols(j,ncols) = ...;
sm1.rightCols(ncols) = ...;
SparseMatrix<double,RowMajor> sm2;
sm2.row(i) = ...;
sm2.topRows(nrows) = ...;
sm2.middleRows(i,nrows) = ...;
sm2.bottomRows(nrows) = ... ;
總結為一句話:列優先的稀疏矩陣只能進行列向操作,行優先的稀疏矩陣只能進行橫向操作
這個限制說明很多Dense矩陣的塊操作對Sparse矩陣來說就不成立了:
對正常的Dense矩陣來說,拼接比較方便,可以直接使用:
M << m1, m2; M << m1, m2;
Dense矩陣可以對整個稀疏矩陣的某個block進行修改,比如只是對上述D部分進行修改,稀疏矩陣是不行的
- Sparse矩陣使用的塊操作更多的用讀取許可權,而沒有寫許可權
在這個限制的前提下,當我們想進行兩維稀疏矩陣的拼接的時候就會很矛盾,舉個例子,我們現在有四個稀疏矩陣A B C D,如下:
參考上面的規則程式碼,如果所有的稀疏矩陣都使用列優先,那麼可以將A B進行列向拼接,即,C D也一樣,但是之後我們就無法將結果的和的結果進行橫向拼接為了。
解決方案
笨方法,用insert進行逐個插值
此時藉助迭代器是一個不錯的選擇,給出一段示例程式:
Eigen::SparseMatrix<double> M_sparse(2*npixels, 2*npixels); M_sparse.reserve(FU_sparse.nonZeros() + FV_sparse.nonZeros()); for(int c=0; c<FU_sparse.cols(); ++c) { for(Eigen::SparseMatrix<double>::InnerIterator itU(FU_sparse, c); itU; ++itU) { if (itU.value()) { M_sparse.insert(itU.row(), c) = -itU.value(); } } }
問題是,當非零元素的數目過w的時候,上述hash-map的insert弊端就會凸顯出來,也是很耗時的。
在上述限制的前提下利用現有介面實現上述過程
我們想要的結果是:
對A、B、C、D進行轉置得到
將A和C、B和D進行列向拼接,得到: