Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F122518600
bsplines.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Fri, Jul 18, 06:57
Size
20 KB
Mime Type
text/x-c
Expires
Sun, Jul 20, 06:57 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
27483796
Attached To
R5163 Slepians
bsplines.c
View Options
/*
* $Id: bsplines.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 "mex.h"
#include <stdlib.h>
#include <math.h>
#ifdef IMAGE_SINGLE
#define IMAGE_DTYPE float
#else
#define IMAGE_DTYPE double
#endif
/***************************************************************************************
Starting periodic boundary condition based on Eq. 2.6 of Unser's 2nd 1993 paper.
c - vector of unfiltered data
m - length of c
p - pole (root of polynomial)
function returns value that c[0] should initially take
The expression for the first pass of the recursive convolution is:
for (i=1; i<m; i++) c[i] += p*c[i-1];
If m==4, then:
c0 = c0 + p*c3;
c1 = c1 + p*c0;
c2 = c2 + p*c1
c3 = c3 + p*c2;
c0 = c0 + p*c3;
etc...
After recursive substitution, c0 becomes:
(1 +p^4+p^8 +p^12 ...)*c0 +
(p +p^5+p^9 +p^13 ...)*c3 +
(p^2+p^6+p^10+p^14 ...)*c2 +
(p^3+p^7+p^11+p^15 ...)*c1
Using maple...
sum('p^(k*m+n)','k'=0..infinity)
These series converge to...
(p^n)/(1-p^m)
So c0 becomes:
(c0 + c3*p + c2*p^2 + c1*p^3)/(1-p^4)
*/
static
double
cc_wrap
(
IMAGE_DTYPE
c
[],
int
m
,
double
p
)
{
double
s
,
pi
;
int
i
,
m1
;
m1
=
ceil
(
-
30
/
log
(
fabs
(
p
)));
if
(
m1
>
m
)
m1
=
m
;
pi
=
p
;
s
=
c
[
0
];
for
(
i
=
1
;
i
<
m1
;
i
++
)
{
s
+=
pi
*
c
[
m
-
i
];
pi
*=
p
;
}
return
(
s
/
(
1.0
-
pi
));
}
/***************************************************************************************
Starting mirrored boundary condition based on Eq. 2.6 of Unser's 2nd 1993 paper.
c - vector of unfiltered data
m - length of c
p - pole (root of polynomial)
function returns value that c[0] should initially take
*/
static
double
cc_mirror
(
IMAGE_DTYPE
c
[],
int
m
,
double
p
)
{
double
s
,
pi
,
p2i
,
ip
;
int
i
,
m1
;
m1
=
ceil
(
-
30
/
log
(
fabs
(
p
)));
if
(
m1
<
m
)
{
pi
=
p
;
s
=
c
[
0
];
for
(
i
=
1
;
i
<
m1
;
i
++
)
{
s
+=
pi
*
c
[
i
];
pi
*=
p
;
}
return
(
s
);
}
else
{
pi
=
p
;
ip
=
1.0
/
p
;
p2i
=
pow
(
p
,
m
-
1.0
);
s
=
c
[
0
]
+
p2i
*
c
[
m
-
1
];
p2i
*=
p2i
*
ip
;
for
(
i
=
1
;
i
<
m
-
1
;
i
++
)
{
s
+=
(
pi
+
p2i
)
*
c
[
i
];
pi
*=
p
;
p2i
*=
ip
;
}
return
(
s
/
(
1.0
-
pi
*
pi
));
}
}
/***************************************************************************************
End periodic boundary condition
c - first pass filtered data
m - length of filtered data (must be > 1)
p - pole
function returns value for c[m-1] before 2nd filter pass
The expression for the second pass of the recursive convolution is:
for (i=m-2; i>=0; i--) c[i] = p*(c[i+1]-c[i]);
If m==4, then:
c3 = p*(c0-c3);
c2 = p*(c3-c2);
c1 = p*(c2-c1);
c0 = p*(c1-c0);
c3 = p*(c0-c3);
etc...
After recursive substitution, c0 becomes:
-(p +p^5+p^9 ...)*c3
-(p^2+p^6+p^10 ...)*c0
-(p^3+p^7+p^11 ...)*c1
-(p^4+p^8+p^12 ...)*c2
These series converge to...
(p^n)/(p^m-1)
So c0 becomes:
(c3*p + c0*p^2 + c1*p^3 + c2*p^4)/(p^4-1)
*/
static
double
icc_wrap
(
IMAGE_DTYPE
c
[],
int
m
,
double
p
)
{
double
s
,
pi
;
int
i
,
m1
;
m1
=
ceil
(
-
30
/
log
(
fabs
(
p
)));
if
(
m1
>
m
)
m1
=
m
;
pi
=
p
;
s
=
pi
*
c
[
m
-
1
];
for
(
i
=
0
;
i
<
m1
-
1
;
i
++
)
{
pi
*=
p
;
s
+=
pi
*
c
[
i
];
}
return
(
s
/
(
pi
-
1.0
));
}
/***************************************************************************************
End mirrored boundary condition
c - first pass filtered data
m - length of filtered data (must be > 1)
p - pole
function returns value for c[m-1] before 2nd filter pass
*/
static
double
icc_mirror
(
IMAGE_DTYPE
c
[],
int
m
,
double
p
)
{
return
((
p
/
(
p
*
p
-
1.0
))
*
(
p
*
c
[
m
-
2
]
+
c
[
m
-
1
]));
}
/***************************************************************************************
Compute gains required for zero-pole representation - see tf2zp.m in Matlab's
Signal Processing Toolbox.
p - poles
np - number of poles
function returns the gain of the system
*/
static
double
gain
(
double
p
[],
int
np
)
{
int
j
;
double
lambda
=
1.0
;
for
(
j
=
0
;
j
<
np
;
j
++
)
lambda
=
lambda
*
(
1.0
-
p
[
j
])
*
(
1.0
-
1.0
/
p
[
j
]);
return
(
lambda
);
}
/***************************************************************************************
One dimensional recursive filtering - assuming wrapped boundaries
See Eq. 2.5 of Unsers 2nd 1993 paper.
c - original vector on input, coefficients on output
m - length of vector
p - poles (polynomial roots)
np - number of poles
*/
void
splinc_wrap
(
IMAGE_DTYPE
c
[],
int
m
,
double
p
[],
int
np
)
{
double
lambda
=
1.0
;
int
i
,
k
;
if
(
m
==
1
)
return
;
/* compute gain and apply it */
lambda
=
gain
(
p
,
np
);
for
(
i
=
0
;
i
<
m
;
i
++
)
c
[
i
]
*=
lambda
;
/* loop over poles */
for
(
k
=
0
;
k
<
np
;
k
++
)
{
double
pp
=
p
[
k
];
c
[
0
]
=
cc_wrap
(
c
,
m
,
pp
);
for
(
i
=
1
;
i
<
m
;
i
++
)
c
[
i
]
+=
pp
*
c
[
i
-
1
];
c
[
m
-
1
]
=
icc_wrap
(
c
,
m
,
pp
);
for
(
i
=
m
-
2
;
i
>=
0
;
i
--
)
c
[
i
]
=
pp
*
(
c
[
i
+
1
]
-
c
[
i
]);
}
}
/***************************************************************************************
One dimensional recursive filtering - assuming mirror boundaries
See Eq. 2.5 of Unsers 2nd 1993 paper.
c - original vector on input, coefficients on output
m - length of vector
p - poles (polynomial roots)
np - number of poles
*/
void
splinc_mirror
(
IMAGE_DTYPE
c
[],
int
m
,
double
p
[],
int
np
)
{
double
lambda
=
1.0
;
int
i
,
k
;
if
(
m
==
1
)
return
;
/* compute gain and apply it */
lambda
=
gain
(
p
,
np
);
for
(
i
=
0
;
i
<
m
;
i
++
)
c
[
i
]
*=
lambda
;
/* loop over poles */
for
(
k
=
0
;
k
<
np
;
k
++
)
{
double
pp
=
p
[
k
];
c
[
0
]
=
cc_mirror
(
c
,
m
,
pp
);
for
(
i
=
1
;
i
<
m
;
i
++
)
c
[
i
]
+=
pp
*
c
[
i
-
1
];
c
[
m
-
1
]
=
icc_mirror
(
c
,
m
,
pp
);
for
(
i
=
m
-
2
;
i
>=
0
;
i
--
)
c
[
i
]
=
pp
*
(
c
[
i
+
1
]
-
c
[
i
]);
}
}
/***************************************************************************************
Return roots of B-spline kernels.
d - degree of B-spline
np - number of roots of magnitude less than one
p - roots.
*/
int
get_poles
(
int
d
,
int
*
np
,
double
p
[])
{
/* Return polynomial roots that are less than one. */
switch
(
d
)
{
case
0
:
*
np
=
0
;
break
;
case
1
:
*
np
=
0
;
break
;
case
2
:
/* roots([1 6 1]) */
*
np
=
1
;
p
[
0
]
=
sqrt
(
8.0
)
-
3.0
;
break
;
case
3
:
/* roots([1 4 1]) */
*
np
=
1
;
p
[
0
]
=
sqrt
(
3.0
)
-
2.0
;
break
;
case
4
:
/* roots([1 76 230 76 1]) */
*
np
=
2
;
p
[
0
]
=
sqrt
(
664.0
-
sqrt
(
438976.0
))
+
sqrt
(
304.0
)
-
19.0
;
p
[
1
]
=
sqrt
(
664.0
+
sqrt
(
438976.0
))
-
sqrt
(
304.0
)
-
19.0
;
break
;
case
5
:
/* roots([1 26 66 26 1]) */
*
np
=
2
;
p
[
0
]
=
sqrt
(
67.5
-
sqrt
(
4436.25
))
+
sqrt
(
26.25
)
-
6.5
;
p
[
1
]
=
sqrt
(
67.5
+
sqrt
(
4436.25
))
-
sqrt
(
26.25
)
-
6.5
;
break
;
case
6
:
/* roots([1 722 10543 23548 10543 722 1]) */
*
np
=
3
;
p
[
0
]
=
-
0.488294589303044755130118038883789062112279161239377608394
;
p
[
1
]
=
-
0.081679271076237512597937765737059080653379610398148178525368
;
p
[
2
]
=
-
0.00141415180832581775108724397655859252786416905534669851652709
;
break
;
case
7
:
/* roots([1 120 1191 2416 1191 120 1]) */
*
np
=
3
;
p
[
0
]
=
-
0.5352804307964381655424037816816460718339231523426924148812
;
p
[
1
]
=
-
0.122554615192326690515272264359357343605486549427295558490763
;
p
[
2
]
=
-
0.0091486948096082769285930216516478534156925639545994482648003
;
break
;
default:
return
(
1
);
}
return
(
0
);
}
/***************************************************************************************/
/***************************************************************************************
Different degrees of B-splines
x - position relative to origin
returns value of basis function at x
*/
/*static double wt1(double x)
{
x = fabs(x);
return((x > 1.0) ? (0.0) : (1.0 - x));
}*/
static
double
wt2
(
double
x
)
{
x
=
fabs
(
x
);
if
(
x
<
0.5
)
return
(
0.75
-
x
*
x
);
if
(
x
<
1.5
)
{
x
=
1.5
-
x
;
return
(
0.5
*
x
*
x
);
}
return
(
0.0
);
}
static
double
wt3
(
double
x
)
{
x
=
fabs
(
x
);
if
(
x
<
1.0
)
return
(
x
*
x
*
(
x
-
2.0
)
*
0.5
+
2.0
/
3.0
);
if
(
x
<
2.0
)
{
x
=
2.0
-
x
;
return
(
x
*
x
*
x
*
(
1.0
/
6.0
));
}
return
(
0.0
);
}
static
double
wt4
(
double
x
)
{
x
=
fabs
(
x
);
if
(
x
<
0.5
)
{
x
*=
x
;
return
(
x
*
(
x
*
0.25
-
0.625
)
+
115.0
/
192.0
);
}
if
(
x
<
1.5
)
return
(
x
*
(
x
*
(
x
*
(
5.0
/
6.0
-
x
*
(
1.0
/
6.0
))
-
1.25
)
+
5.0
/
24.0
)
+
55.0
/
96.0
);
if
(
x
<
2.5
)
{
x
-=
2.5
;
x
*=
x
;
return
(
x
*
x
*
(
1.0
/
24.0
));
}
return
(
0.0
);
}
static
double
wt5
(
double
x
)
{
double
y
;
x
=
fabs
(
x
);
if
(
x
<
1.0
)
{
y
=
x
*
x
;
return
(
y
*
(
y
*
(
0.25
-
x
*
(
1.0
/
12.0
))
-
0.5
)
+
0.55
);
}
if
(
x
<
2.0
)
return
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
1.0
/
24.0
)
-
0.375
)
+
1.25
)
-
1.75
)
+
0.625
)
+
0.425
);
if
(
x
<
3.0
)
{
y
=
3.0
-
x
;
x
=
y
*
y
;
return
(
y
*
x
*
x
*
(
1.0
/
120.0
));
}
return
(
0.0
);
}
static
double
wt6
(
double
x
)
{
x
=
fabs
(
x
);
if
(
x
<
0.5
)
{
x
*=
x
;
return
(
x
*
(
x
*
(
7.0
/
48.0
-
x
*
(
1.0
/
36.0
))
-
77.0
/
192.0
)
+
5887.0
/
11520.0
);
}
if
(
x
<
1.5
)
return
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
1.0
/
48.0
)
-
7.0
/
48.0
)
+
0.328125
)
-
35.0
/
288.0
)
-
91.0
/
256.0
)
-
7.0
/
768.0
)
+
7861.0
/
15360.0
);
if
(
x
<
2.5
)
return
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
7.0
/
60.0
-
x
*
(
1.0
/
120.0
))
-
0.65625
)
+
133.0
/
72.0
)
-
2.5703125
)
+
1267.0
/
960.0
)
+
1379.0
/
7680.0
);
if
(
x
<
3.5
)
{
x
-=
3.5
;
x
*=
x
*
x
;
return
(
x
*
x
*
(
1.0
/
720.0
));
}
return
(
0.0
);
}
static
double
wt7
(
double
x
)
{
double
y
;
x
=
fabs
(
x
);
if
(
x
<
1.0
)
{
y
=
x
*
x
;
return
(
y
*
(
y
*
(
y
*
(
x
*
(
1.0
/
144.0
)
-
1.0
/
36.0
)
+
1.0
/
9.0
)
-
1.0
/
3.0
)
+
151.0
/
315.0
);
}
if
(
x
<
2.0
)
return
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
0.05
-
x
*
(
1.0
/
240.0
))
-
7.0
/
30.0
)
+
0.5
)
-
7.0
/
18.0
)
-
0.1
)
-
7.0
/
90.0
)
+
103.0
/
210.0
);
if
(
x
<
3.0
)
return
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
1.0
/
720.0
)
-
1.0
/
36.0
)
+
7.0
/
30.0
)
-
19.0
/
18.0
)
+
49.0
/
18.0
)
-
23.0
/
6.0
)
+
217.0
/
90.0
)
-
139.0
/
630.0
);
if
(
x
<
4.0
)
{
y
=
4.0
-
x
;
x
=
y
*
y
*
y
;
return
(
x
*
x
*
y
*
(
1.0
/
5040.0
));
}
return
(
0.0
);
}
/***************************************************************************************
Derivatives of different degrees of B-splines
x - position relative to origin
returns derivative of basis function at x
*/
static
double
dwt2
(
double
x
)
{
int
s
;
s
=
(
x
>
0
?
1
:
-
1
);
x
=
fabs
(
x
);
if
(
x
<
0.5
)
return
(
-
2
*
x
*
s
);
if
(
x
<
1.5
)
return
((
x
-
1.5
)
*
s
);
return
(
0.0
);
}
static
double
dwt3
(
double
x
)
{
int
s
;
s
=
(
x
>
0
?
1
:
-
1
);
x
=
fabs
(
x
);
if
(
x
<
1.0
)
return
(
x
*
(
1.5
*
x
-
2.0
)
*
s
);
if
(
x
<
2.0
)
{
x
=
x
-
2.0
;
return
(
-
0.5
*
x
*
x
*
s
);
}
return
(
0.0
);
}
static
double
dwt4
(
double
x
)
{
int
s
;
s
=
(
x
>
0
?
1
:
-
1
);
x
=
fabs
(
x
);
if
(
x
<
0.5
)
{
return
((
x
*
(
x
*
x
-
5.0
/
4.0
))
*
s
);
}
if
(
x
<
1.5
)
return
((
x
*
(
x
*
(
x
*
(
-
2.0
/
3.0
)
+
2.5
)
-
5.0
/
2.0
)
+
5.0
/
24.0
)
*
s
);
if
(
x
<
2.5
)
{
x
=
x
*
2.0
-
5.0
;
return
((
1.0
/
48.0
)
*
x
*
x
*
x
*
s
);
}
return
(
0.0
);
}
static
double
dwt5
(
double
x
)
{
int
s
;
s
=
(
x
>
0
?
1
:
-
1
);
x
=
fabs
(
x
);
if
(
x
<
1.0
)
return
((
x
*
(
x
*
(
x
*
(
x
*
(
-
5.0
/
12.0
)
+
1.0
))
-
1.0
))
*
s
);
if
(
x
<
2.0
)
return
((
x
*
(
x
*
(
x
*
(
x
*
(
5.0
/
24.0
)
-
1.5
)
+
3.75
)
-
3.5
)
+
0.625
)
*
s
);
if
(
x
<
3.0
)
{
x
-=
3.0
;
x
*=
x
;
return
((
-
1.0
/
24.0
)
*
x
*
x
*
s
);
}
return
(
0.0
);
}
static
double
dwt6
(
double
x
)
{
double
y
;
int
s
;
s
=
(
x
>
0
?
1
:
-
1
);
x
=
fabs
(
x
);
if
(
x
<
0.5
)
{
y
=
x
*
x
;
return
(
x
*
((
7.0
/
12.0
)
*
y
-
(
1.0
/
6.0
)
*
y
*
y
-
(
77.0
/
96.0
))
*
s
);
}
if
(
x
<
1.5
)
return
((
x
*
(
x
*
(
x
*
(
x
*
(
x
*
0.125
-
35.0
/
48.0
)
+
1.3125
)
-
35.0
/
96.0
)
-
0.7109375
)
-
7.0
/
768.0
)
*
s
);
if
(
x
<
2.5
)
return
((
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
-
1.0
/
20.0
)
+
7.0
/
12.0
)
-
2.625
)
+
133.0
/
24.0
)
-
5.140625
)
+
1267.0
/
960.0
)
*
s
);
if
(
x
<
3.5
)
{
x
*=
2.0
;
x
-=
7.0
;
y
=
x
*
x
;
return
((
1.0
/
3840.0
)
*
y
*
y
*
x
*
s
);
}
return
(
0.0
);
}
static
double
dwt7
(
double
x
)
{
double
y
;
int
s
;
s
=
(
x
>
0
?
1
:
-
1
);
x
=
fabs
(
x
);
if
(
x
<
1.0
)
{
y
=
x
*
x
;
return
(
x
*
(
y
*
(
y
*
(
x
*
(
7.0
/
144.0
)
-
1.0
/
6.0
)
+
4.0
/
9.0
)
-
2.0
/
3.0
)
*
s
);
}
if
(
x
<
2.0
)
return
((
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
-
7.0
/
240.0
)
+
3.0
/
10.0
)
-
7.0
/
6.0
)
+
2.0
)
-
7.0
/
6.0
)
-
1.0
/
5.0
)
-
7.0
/
90.0
)
*
s
);
if
(
x
<
3.0
)
return
((
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
x
*
(
7.0
/
720.0
)
-
1.0
/
6.0
)
+
7.0
/
6.0
)
-
38.0
/
9.0
)
+
49.0
/
6.0
)
-
23.0
/
3.0
)
+
217.0
/
90.0
)
*
s
);
if
(
x
<
4.0
)
{
x
-=
4
;
x
*=
x
*
x
;
x
*=
x
;
return
((
-
1.0
/
720.0
)
*
x
*
s
);
}
return
(
0.0
);
}
/***************************************************************************************
Generate B-spline basis functions
d - degree of spline
x - position relative to centre
i - pointer to first voxel position in convolution
w - vector of spline values
Should really combine this function with wt2 to wt7 for most
efficiency (as for case 0).
Note that 0th degree B-spline returns nearest neighbour basis.
*/
static
void
weights
(
int
d
,
double
x
,
int
*
i
,
double
w
[])
{
int
k
;
*
i
=
floor
(
x
-
(
d
-
1
)
*
0.5
);
x
-=
*
i
;
switch
(
d
){
case
2
:
for
(
k
=
0
;
k
<=
2
;
k
++
)
w
[
k
]
=
wt2
(
x
-
k
);
break
;
case
3
:
for
(
k
=
0
;
k
<=
3
;
k
++
)
w
[
k
]
=
wt3
(
x
-
k
);
break
;
case
4
:
for
(
k
=
0
;
k
<=
4
;
k
++
)
w
[
k
]
=
wt4
(
x
-
k
);
break
;
case
5
:
for
(
k
=
0
;
k
<=
5
;
k
++
)
w
[
k
]
=
wt5
(
x
-
k
);
break
;
case
6
:
for
(
k
=
0
;
k
<=
6
;
k
++
)
w
[
k
]
=
wt6
(
x
-
k
);
break
;
case
7
:
for
(
k
=
0
;
k
<=
7
;
k
++
)
w
[
k
]
=
wt7
(
x
-
k
);
break
;
case
1
:
w
[
0
]
=
1.0
-
x
;
w
[
1
]
=
x
;
break
;
case
0
:
w
[
0
]
=
1.0
;
/* Not correct at discontinuities */
break
;
default:
for
(
k
=
0
;
k
<=
7
;
k
++
)
w
[
k
]
=
wt7
(
x
-
k
);
}
}
/***************************************************************************************
Generate derivatives of B-spline basis functions
d - degree of spline
x - position relative to centre
i - pointer to first voxel position in convolution
w - vector of spline values
Should really combine this function with dwt2 to dwt7 for most
efficiency (as for case 0 and case 1).
Note that 0th and 1st degree B-spline return derivatives of
nearest neighbour and linear interpolation bases.
*/
static
void
dweights
(
int
d
,
double
x
,
int
*
i
,
double
w
[])
{
int
k
;
*
i
=
floor
(
x
-
(
d
-
1
)
*
0.5
);
x
-=
*
i
;
switch
(
d
){
case
2
:
for
(
k
=
0
;
k
<=
2
;
k
++
)
w
[
k
]
=
dwt2
(
x
-
k
);
break
;
case
3
:
for
(
k
=
0
;
k
<=
3
;
k
++
)
w
[
k
]
=
dwt3
(
x
-
k
);
break
;
case
4
:
for
(
k
=
0
;
k
<=
4
;
k
++
)
w
[
k
]
=
dwt4
(
x
-
k
);
break
;
case
5
:
for
(
k
=
0
;
k
<=
5
;
k
++
)
w
[
k
]
=
dwt5
(
x
-
k
);
break
;
case
6
:
for
(
k
=
0
;
k
<=
6
;
k
++
)
w
[
k
]
=
dwt6
(
x
-
k
);
break
;
case
7
:
for
(
k
=
0
;
k
<=
7
;
k
++
)
w
[
k
]
=
dwt7
(
x
-
k
);
break
;
case
1
:
w
[
0
]
=
-
1.0
;
/* Not correct at discontinuities */
w
[
1
]
=
1.0
;
/* Not correct at discontinuities */
break
;
case
0
:
w
[
0
]
=
0.0
;
/* Not correct at discontinuities */
break
;
default:
for
(
k
=
0
;
k
<=
7
;
k
++
)
w
[
k
]
=
dwt7
(
x
-
k
);
}
}
/***************************************************************************************
Work out what to do with positions outside the FOV
i - Co-ordinate (0<=i<m)
m - dimension
returns reflected co-ordinate
*/
int
mirror
(
int
i
,
int
m
)
{
int
m2
;
i
=
abs
(
i
);
if
(
i
<
m
)
return
(
i
);
if
(
m
==
1
)
return
(
0
);
m2
=
(
m
-
1
)
*
2
;
i
%=
m2
;
return
((
i
<
m
)
?
i
:
m2
-
i
);
}
/***************************************************************************************
Work out what to do with positions outside the FOV
i - Co-ordinate (0<=i<m)
m - dimension
returns wrapped co-ordinate
For MRI, it may be better to wrap the boundaries
- especially in the read and phase encode directions.
*/
int
wrap
(
int
i
,
int
m
)
{
if
(
i
<
0
)
return
(
m
-
1
-
((
-
i
-
1
)
%
m
));
return
(
i
%
m
);
}
/***************************************************************************************
Resample a point
c - Volume of B-spline coefficients
m0,m1,m2 - dimensions of c
x0,x1,x2 - co-ordinate to sample
d - degrees of splines used
returns value of sampled point
*/
IMAGE_DTYPE
sample3
(
IMAGE_DTYPE
c
[],
int
m0
,
int
m1
,
int
m2
,
IMAGE_DTYPE
x0
,
IMAGE_DTYPE
x1
,
IMAGE_DTYPE
x2
,
int
d
[],
int
(
*
bnd
[])())
{
double
w0
[
32
],
w1
[
32
],
w2
[
32
];
/* B-spline weights */
int
o0
[
32
],
o1
[
32
],
o2
[
32
];
/* Offsets */
int
i0
,
i1
,
i2
;
/* Initial offsets */
double
d0
,
d1
,
d2
;
/* Used by seperable convolution */
int
k
;
IMAGE_DTYPE
*
cp
;
/* Generate seperable B-spline basis functions */
weights
(
d
[
0
],
x0
,
&
i0
,
w0
);
weights
(
d
[
1
],
x1
,
&
i1
,
w1
);
weights
(
d
[
2
],
x2
,
&
i2
,
w2
);
/* Create lookups of voxel locations - for coping with edges */
for
(
k
=
0
;
k
<=
d
[
0
];
k
++
)
o0
[
k
]
=
bnd
[
0
](
k
+
i0
,
m0
);
for
(
k
=
0
;
k
<=
d
[
1
];
k
++
)
o1
[
k
]
=
bnd
[
1
](
k
+
i1
,
m1
)
*
m0
;
for
(
k
=
0
;
k
<=
d
[
2
];
k
++
)
o2
[
k
]
=
bnd
[
2
](
k
+
i2
,
m2
)
*
(
m0
*
m1
);
/* Convolve coefficients with basis functions */
d2
=
0.0
;
for
(
i2
=
0
;
i2
<=
d
[
2
];
i2
++
)
{
d1
=
0.0
;
for
(
i1
=
0
;
i1
<=
d
[
1
];
i1
++
)
{
cp
=
c
+
o2
[
i2
]
+
o1
[
i1
];
d0
=
0.0
;
for
(
i0
=
0
;
i0
<=
d
[
0
];
i0
++
)
d0
+=
cp
[
o0
[
i0
]]
*
w0
[
i0
];
d1
+=
d0
*
w1
[
i1
];
}
d2
+=
d1
*
w2
[
i2
];
}
return
((
IMAGE_DTYPE
)
d2
);
}
/***************************************************************************************
Resample a point and its gradients
c - Volume of B-spline coefficients
m0,m1,m2 - dimensions of c
x0,x1,x2 - co-ordinate to sample
d - degrees of splines used
pg0,pg1,pg2 - gradients
returns value of sampled point
*/
IMAGE_DTYPE
dsample3
(
IMAGE_DTYPE
c
[],
int
m0
,
int
m1
,
int
m2
,
IMAGE_DTYPE
x0
,
IMAGE_DTYPE
x1
,
IMAGE_DTYPE
x2
,
int
d
[],
IMAGE_DTYPE
*
pg0
,
IMAGE_DTYPE
*
pg1
,
IMAGE_DTYPE
*
pg2
,
int
(
*
bnd
[])())
{
double
w0
[
32
],
w1
[
32
],
w2
[
32
];
/* B-spline weights */
double
dw0
[
32
],
dw1
[
32
],
dw2
[
32
];
/* B-spline derivatives */
int
o0
[
32
],
o1
[
32
],
o2
[
32
];
/* Offsets */
int
i0
,
i1
,
i2
;
/* Initial offsets */
double
d0
,
d1
,
d2
;
/* Used by seperable convolution */
double
g00
,
g10
,
g11
,
g20
,
g21
,
g22
;
/* Used for generating gradients */
int
k
;
IMAGE_DTYPE
*
cp
;
/* Generate seperable B-spline basis functions */
weights
(
d
[
0
],
x0
,
&
i0
,
w0
);
weights
(
d
[
1
],
x1
,
&
i1
,
w1
);
weights
(
d
[
2
],
x2
,
&
i2
,
w2
);
dweights
(
d
[
0
],
x0
,
&
i0
,
dw0
);
dweights
(
d
[
1
],
x1
,
&
i1
,
dw1
);
dweights
(
d
[
2
],
x2
,
&
i2
,
dw2
);
/* Create lookups of voxel locations - for coping with edges */
for
(
k
=
0
;
k
<=
d
[
0
];
k
++
)
o0
[
k
]
=
bnd
[
0
](
k
+
i0
,
m0
);
for
(
k
=
0
;
k
<=
d
[
1
];
k
++
)
o1
[
k
]
=
bnd
[
1
](
k
+
i1
,
m1
)
*
m0
;
for
(
k
=
0
;
k
<=
d
[
2
];
k
++
)
o2
[
k
]
=
bnd
[
2
](
k
+
i2
,
m2
)
*
(
m0
*
m1
);
/* Convolve coefficients with basis functions */
g20
=
g21
=
g22
=
d2
=
0.0
;
for
(
i2
=
0
;
i2
<=
d
[
2
];
i2
++
)
{
g10
=
g11
=
d1
=
0.0
;
for
(
i1
=
0
;
i1
<=
d
[
1
];
i1
++
)
{
cp
=
c
+
o2
[
i2
]
+
o1
[
i1
];
g00
=
d0
=
0.0
;
for
(
i0
=
0
;
i0
<=
d
[
0
];
i0
++
)
{
d0
+=
cp
[
o0
[
i0
]]
*
w0
[
i0
];
g00
+=
cp
[
o0
[
i0
]]
*
dw0
[
i0
];
}
d1
+=
d0
*
w1
[
i1
];
g10
+=
g00
*
w1
[
i1
];
g11
+=
d0
*
dw1
[
i1
];
}
d2
+=
d1
*
w2
[
i2
];
g20
+=
g10
*
w2
[
i2
];
g21
+=
g11
*
w2
[
i2
];
g22
+=
d1
*
dw2
[
i2
];
}
*
pg0
=
g20
;
*
pg1
=
g21
;
*
pg2
=
g22
;
return
((
IMAGE_DTYPE
)
d2
);
}
Event Timeline
Log In to Comment