"真理本身之所以是真理,就在于它穿透了语言的有限性而将人带入到对真实世界的直观把握中。"
——http://my1510.cn/article.php?id=69054
最近在做sparse coding, 用Bruno Olshausen最原始的方法, 因此却发现了一些背后直感上更接近真理的东西。中间有一步需要通过得到的sparse响应重建输入图像,之前一直是用Matlab for循环直接解决的,但是速度奇慢,于是今天尝试了一下把这一部分加速。
首先考虑的是fft2->ifft2的方法,代码如下(参考了http://www.mathworks.com/matlabcentral/newsreader/author/121671):
- % Load image
- image = im2double(imread('./data/lena.png'));
- % image=image(201:240,201:240);
- [M N] = size(image);
- figure(101),subplot(1,2,1),imshow(image,[]);
- % Here filter should be a 7x7 patch
- filter = reshape(A(:,2),[7,7]);
- % Get the filtered response in fft2
- F=fft2(image);
- H=fft2(filter,M,N);
- G=H.*F;
- Gnew= G./H;
- gnew=real(ifft2(double(Gnew)));
- figure(101),subplot(1,2,2),imshow(gnew,[]);
出来的结果是正常。
但由于sparse coding的方法并不是直接利用滤波后响应而是将这个响应离散化并且在时间上积累(可以看成是神经元
的membrane potential随着spike的输入而增高)
我实际implement的code是
- % Load image
- image = im2double(imread('./data/lena.png'));
- % image=image(201:240,201:240);
- [M N] = size(image);
- figure(101),subplot(1,2,1),imshow(image,[]);
- % Here filter should be a 7x7 patch
- filter = reshape(A(:,2),[7,7]);
- % Get the filtered response in fft2
- F=fft2(image);
- H=fft2(filter,M,N);
- G=H.*F;
- % for ISTA or LCA algorithm
- g=real(ifft2(double(G)));
- g=g/10;
- g=max(abs(g)-0.01,0).*sign(g);
- G=fft2(g);
- Gnew= G./H;
- gnew=real(ifft2(double(Gnew)));
- figure(101),subplot(1,2,2),imshow(gnew,[]);
结果出来的结果就如下图中间一幅所示,与用filter乘以sparse响应重建的有一定差距
图1,原图(左), fft2->ifft2结果(中), sparse coding直接重建结果(右)
所以就不得不用c+mex的方法写了一个2d image的deconvolution 程序,mex文件代码如下:
- #include <stdio.h>
- #include <math.h>
- #include "mex.h"
- #define a_IN prhs[0] /* sparse coefficient matrix */
- #define f_IN prhs[1] /* filter matrix*/
- #define fb_OUT plhs[0] /* reconstructed image */
- #define a_(i,n) a[(i) + (n)*ra] /* A is L x M */
- #define f_(i,n) f[(i) + (n)*rf] /* X is L x npats */
- #define fb_(i,n) fb[(i) + (n)*rfb] /* S is M x npats */
- static int ra; /* row number of a */
- static int ca; /* column number of a */
- static int rf; /* row number of f */
- static int cf; /* column number of f */
- static int rfb; /* row number of fb */
- static int cfb; /* column number of fb */
- // const mwSize N_DIM=2;
- void mexFunction(int nlhs, mxArray *plhs[],
- int nrhs, const mxArray *prhs[])
- {
- if (mxGetNumberOfDimensions(a_IN)!=2 || mxGetNumberOfDimensions(f_IN)!=2){
- mexErrMsgTxt("Both inputs should be 2D matrix.");
- }
- double *a, *f, *fb;
- a = mxGetPr(a_IN);
- f = mxGetPr(f_IN);
- ra = (int)mxGetM(a_IN);
- ca = (int)mxGetN(a_IN);
- rf = (int)mxGetM(f_IN);
- cf = (int)mxGetN(f_IN);
- rfb = ra+rf-1;
- cfb = ca+cf-1;
- fb_OUT = mxCreateDoubleMatrix(rfb, cfb, mxREAL);
- fb = mxGetPr(fb_OUT);
- //printf("a: %d, %d\n f: %d, %d\n fb: %d, %d\n", ra,ca,rf,cf,rfb,cfb);
- //initialize fb to zero;
- for (int i=0;i<rfb;i++){
- for (int j=0;j<cfb;j++){
- fb_(i,j)=0;
- }
- }
- for (int i=0;i<ra;i++){
- for (int j=0;j<ca;j++){
- if (a_(i,j)!=0){
- for (int i1=0;i1<rf;i1++){
- for (int j1=0;j1<cf;j1++){
- fb_(i+i1,j+j1)+=a_(i,j)*f_(i1,j1);
- }
- }
- }
- }
- }
- }
把这个文件命名成deconv2.cpp 再在matlab里面mex deconv2.cpp编译一下,就是2d deconvolution函数了。运行速度比原来matlab code提高了1000倍左右
后记:后来发现原来这样implement没有必要,matlab里面conv2就能实现这个功能,只不过要得到正确结果的话要先把filter行列反转一下