基于Eigen库的离散拉普拉斯平滑(Discretized Laplacian Smoothing)的C++非稀疏矩阵实现

转载请注明出处:http://my.csdn.net/ye_shen_wei_mian

离散拉普拉斯平滑很多时候被用于图像的平滑处理,在一些论文的cost function里面也可以见到离散拉普拉斯平滑项,本文就离散的拉普拉斯平滑项进行基于Eigen库的非稀疏矩阵的C++实现。

离散拉普拉斯平滑项的实现原理可以参考Deng Cai(蔡登)大神的《Learning a Spatially Smooth Subspace for Face Recognition》,蔡登的主页是 http://www.cad.zju.edu.cn/home/dengcai/ ,而离散拉普拉斯平滑项的具体原理可能就要参考Finbarr O'Sullivan的《DISCRETIZED LAPLACIAN SMOOTHING BY FOURIER  METHODS》了。

在蔡登大神的网站里,可以找到相应的Matlab的代码,本文就是根据其Matlab代码进行C++的复现的。

先贴上Deng Cai大神的Matlab代码(原网址:http://www.cad.zju.edu.cn/home/dengcai/Data/code/GenSpatialSmoothRegularizer.m):

<textarea readonly="readonly" name="code" class="c++"> function [R] = GenSpatialSmoothRegularizer(nRow,nCol) % function [R] = GenSpatialSmoothRegularizer(nRow,nCol) % Usage: % R = GenSpatialSmoothRegularizer(nRow,nCol) % % nRow,nCol : dimensions of the images. % % R : the spatially smooth regularizer % % References: % [1] Deng Cai, Xiaofei He, Yuxiao Hu, Jiawei Han and Thomas Huang, % &quot;Learning a Spatially Smooth Subspace for Face Recognition&quot;, CVPR'07. % % version 1.0 --May/2006 % % Written by Deng Cai (dengcai2 AT gmail.com) % B = ones(nRow,3); B(:,2) = -2; B(1,2) = -1; B(end,2) = -1; D = spdiags(B,[-1,0,1],nRow,nRow); I = speye(nCol); M = kron(D,I); B = ones(nCol,3); B(:,2) = -2; B(1,2) = -1; B(end,2) = -1; D = spdiags(B,[-1,0,1],nCol,nCol); I = speye(nRow); M2 = kron(I,D); M = M+M2; R = M'*M; R = max(R,R'); </textarea>

现在贴上自己复现的C++代码:

<textarea readonly="readonly" name="code" class="c++"> MatrixXi my_spdiags(MatrixXi tB, int m) { MatrixXi D = MatrixXi::Zero(m,m); for (int ith = 0; ith &lt; m ; ++ith) { if(ith == 0 ) { D(0,0) = tB(0,1); D(0,1) = tB(0,2); }else if(ith == m-1) { D(m-1,m-2) = tB(m-1,0); D(m-1,m-1) = tB(m-1,1); }else{ D(ith,ith-1) = tB(ith,0); D(ith,ith) = tB(ith,1); D(ith,ith+1) = tB(ith,2); } } return D; } //compute Delta.T * Delta Eigen::MatrixXi discretizedLaplacianSmoothingTerm(int nRow,int nCol) { MatrixXi B1 = MatrixXi::Ones(nRow,3); B1.col(1) = -2 * B1.col(1); B1(0,1) = -1; B1(nRow-1,1) = -1; MatrixXi D1 = my_spdiags(B1 , nRow); MatrixXi I1 = MatrixXi::Identity(nCol,nCol); MatrixXi M = Eigen::kroneckerProduct(D1,I1); MatrixXi B2 = MatrixXi::Ones(nCol,3); B2.col(1) = -2 * B2.col(1); B2(0,1) = -1; B2(nCol-1,1) = -1; MatrixXi D2 = my_spdiags(B2 , nCol); MatrixXi I2 = MatrixXi::Identity(nRow,nRow); MatrixXi M2 = Eigen::kroneckerProduct(I2,D2); M = M + M2; //Delta MatrixXi R(nRow * nCol , nRow * nCol); R = M.transpose() * M; //Delta.T * Delta R = R.array().max((R.transpose()).array()); //cout&lt;&lt;&quot;Matrix B is :\n&quot;&lt;&lt;B1&lt;&lt;endl; //cout&lt;&lt;&quot;Matrix D is :\n&quot;&lt;&lt;D1&lt;&lt;endl; //cout&lt;&lt;&quot;Matrix I is :\n&quot;&lt;&lt;I1&lt;&lt;endl; //cout&lt;&lt;&quot;Matrix M is :\n&quot;&lt;&lt;M&lt;&lt;endl; return R; } </textarea>

存在的问题:

1、本C++实现仅是对Deng Cai的Matlab代码的非稀疏矩阵实现,若应用在图像处理中,应考虑采用稀疏矩阵的形式进行实现,否则可能会出现内存不足的问题。

2、在使用Eigen::kroneckerProduct()时,若发现自己的Eigen库中并没有包含这个函数,原因是使用的Eigen库版本太过落后导致的,新的版本(例如EIgen3)都已经包含这个函数。若无法使用这个函数而又不想重新装库配置的话,解决方法是,上EIgen的网站将KroneckerTensorProduct.h文件(http://eigen.tuxfamily.org/dox-devel/unsupported/KroneckerTensorProduct_8h_source.html)中的内容拷贝到自己新建的.h文件中,然后再include该文件即可解决。

你可能感兴趣的:(Eigen,离散拉普拉斯平滑项,Discretized,非稀疏实现,Laplacia)