-
Notifications
You must be signed in to change notification settings - Fork 55
/
Copy pathspm_bsplinc.c
177 lines (159 loc) · 4.9 KB
/
spm_bsplinc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
/*
* $Id: spm_bsplinc.c 4624 2012-01-13 13:27:08Z john $
* John Ashburner
*/
/*
* This code is a modified version of that of Philippe Thevenaz, which I took from:
* http://bigwww.epfl.ch/algorithms.html
*
* It has been substantially modified, so blame me (John Ashburner) if there
* are any bugs. Many thanks to Philippe Thevenaz for advice with the code.
*
* See:
* M. Unser, A. Aldroubi and M. Eden.
* "B-Spline Signal Processing: Part I-Theory,"
* IEEE Transactions on Signal Processing 41(2):821-832 (1993).
*
* M. Unser, A. Aldroubi and M. Eden.
* "B-Spline Signal Processing: Part II-Efficient Design and Applications,"
* IEEE Transactions on Signal Processing 41(2):834-848 (1993).
*
* M. Unser.
* "Splines: A Perfect Fit for Signal and Image Processing,"
* IEEE Signal Processing Magazine 16(6):22-38 (1999).
*
*/
#include <math.h>
#include "mex.h"
#include "spm_mapping.h"
#include "bsplines.h"
/***************************************************************************************
Deconvolve the B-spline basis functions from the image volume
vol - a handle for the volume to deconvolve
c - the coefficients (arising from the deconvolution)
d - the spline degree
splinc0, splinc1, splinc2 - functions for 1D deconvolutions
*/
static int vol_coeffs(MAPTYPE *vol, double c[], int d[], void (*splinc[])())
{
double p[4];
double *cp;
int np;
int i, j, k, n;
double f[10240];
/* Check that dimensions don't exceed size of f */
if (vol->dim[1]>10240 ||vol->dim[2]>10240)
return(1);
/* Do a straight copy */
cp = c;
for(k=0; k<vol->dim[2]; k++)
{
double dk = k+1;
for(j=0; j<vol->dim[1]; j++)
{
double dj = j+1;
for(i=0;i<vol->dim[0];i++, cp++)
{
double di = i+1;
resample(1,vol,cp,&di,&dj,&dk,0, 0.0);
/* Not sure how best to handle NaNs */
if (!mxIsFinite(*cp)) *cp = 0.0;
}
}
}
/* Deconvolve along the fastest dimension (X) */
if (d[0]>1 && vol->dim[0]>1)
{
if (get_poles(d[0], &np, p)) return(1);
for(k=0; k<vol->dim[2]; k++)
{
/* double dk = k+1; */
for(j=0; j<vol->dim[1]; j++)
{
cp = &c[vol->dim[0]*(j+vol->dim[1]*k)];
splinc[0](cp, vol->dim[0], p, np);
}
}
}
/* Deconvolve along the middle dimension (Y) */
if (d[1]>1 && vol->dim[1]>1)
{
if (get_poles(d[1], &np, p)) return(1);
n =vol->dim[0];
for(k=0; k<vol->dim[2]; k++)
{
for(i=0;i<vol->dim[0];i++)
{
cp = &c[i+vol->dim[0]*vol->dim[1]*k];
for(j=0; j<vol->dim[1]; j++, cp+=n)
f[j] = *cp;
splinc[1](f, vol->dim[1], p, np);
cp = &c[i+vol->dim[0]*vol->dim[1]*k];
for(j=0; j<vol->dim[1]; j++, cp+=n)
*cp = f[j];
}
}
}
/* Deconvolve along the slowest dimension (Z) */
if (d[2]>1 && vol->dim[2]>1)
{
if (get_poles(d[2], &np, p)) return(1);
n = vol->dim[0]*vol->dim[1];
for(j=0; j<vol->dim[1]; j++)
{
for(i=0;i<vol->dim[0];i++)
{
cp = &c[i+vol->dim[0]*j];
for(k=0; k<vol->dim[2]; k++, cp+=n)
f[k] = *cp;
splinc[2](f, vol->dim[2], p, np);
cp = &c[i+vol->dim[0]*j];
for(k=0; k<vol->dim[2]; k++, cp+=n)
*cp = f[k];
}
}
}
return(0);
}
/***************************************************************************************
*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
int k, d[3], sts;
MAPTYPE *vol, *get_maps();
double *c;
void (*splinc[3])();
if (nrhs < 2 || nlhs > 1)
mexErrMsgTxt("Incorrect usage.");
if (mxIsComplex(prhs[1]) || mxIsSparse(prhs[1]) ||
(mxGetM(prhs[1])*mxGetN(prhs[1]) != 3 && mxGetM(prhs[1])*mxGetN(prhs[1]) != 6))
mexErrMsgTxt("Incorrect usage.");
for(k=0; k<3; k++)
{
d[k] = floor(mxGetPr(prhs[1])[k]+0.5);
if (d[k]<0 || d[k]>7)
mexErrMsgTxt("Bad spline degree.");
}
for(k=0; k<3; k++) splinc[k] = splinc_mirror;
if (mxGetM(prhs[1])*mxGetN(prhs[1]) == 6)
{
for(k=0; k<3; k++)
if (mxGetPr(prhs[1])[k+3])
splinc[k] = splinc_wrap;
}
vol=get_maps(prhs[0], &k);
if (k!=1)
{
free_maps(vol, k);
mexErrMsgTxt("Too many images.");
}
plhs[0] = mxCreateNumericArray(3,vol->dim, mxDOUBLE_CLASS, mxREAL);
c = (double *)mxGetPr(plhs[0]);
sts = vol_coeffs(vol, c, d, splinc);
if (sts)
{
free_maps(vol, k);
mexErrMsgTxt("Problem with deconvolution.");
}
free_maps(vol, k);
}