/
finite_radon_transform.py
134 lines (101 loc) · 3.15 KB
/
finite_radon_transform.py
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
"""
:author: Gary Ruben, 2009
:license: modified BSD
"""
__all__ = ["frt2", "ifrt2"]
import numpy as np
from numpy import roll, newaxis
def frt2(a):
"""Compute the 2-dimensional finite radon transform (FRT) for an n x n
integer array.
Parameters
----------
a : array_like
A 2-D square n x n integer array.
Returns
-------
FRT : 2-D ndarray
Finite Radon Transform array of (n+1) x n integer coefficients.
See Also
--------
ifrt2 : The two-dimensional inverse FRT.
Notes
-----
The FRT has a unique inverse if and only if n is prime. [FRT]
The idea for this algorithm is due to Vlad Negnevitski.
Examples
--------
Generate a test image:
Use a prime number for the array dimensions
>>> SIZE = 59
>>> img = np.tri(SIZE, dtype=np.int32)
Apply the Finite Radon Transform:
>>> f = frt2(img)
References
----------
.. [FRT] A. Kingston and I. Svalbe, "Projective transforms on periodic
discrete image arrays," in P. Hawkes (Ed), Advances in Imaging
and Electron Physics, 139 (2006)
"""
if a.ndim != 2 or a.shape[0] != a.shape[1]:
raise ValueError("Input must be a square, 2-D array")
ai = a.copy()
n = ai.shape[0]
f = np.empty((n + 1, n), np.uint32)
f[0] = ai.sum(axis=0)
for m in range(1, n):
# Roll the pth row of ai left by p places
for row in range(1, n):
ai[row] = roll(ai[row], -row)
f[m] = ai.sum(axis=0)
f[n] = ai.sum(axis=1)
return f
def ifrt2(a):
"""Compute the 2-dimensional inverse finite radon transform (iFRT) for
an (n+1) x n integer array.
Parameters
----------
a : array_like
A 2-D (n+1) row x n column integer array.
Returns
-------
iFRT : 2-D n x n ndarray
Inverse Finite Radon Transform array of n x n integer coefficients.
See Also
--------
frt2 : The two-dimensional FRT
Notes
-----
The FRT has a unique inverse if and only if n is prime.
See [1]_ for an overview.
The idea for this algorithm is due to Vlad Negnevitski.
Examples
--------
>>> SIZE = 59
>>> img = np.tri(SIZE, dtype=np.int32)
Apply the Finite Radon Transform:
>>> f = frt2(img)
Apply the Inverse Finite Radon Transform to recover the input
>>> fi = ifrt2(f)
Check that it's identical to the original
>>> assert len(np.nonzero(img-fi)[0]) == 0
References
----------
.. [1] A. Kingston and I. Svalbe, "Projective transforms on periodic
discrete image arrays," in P. Hawkes (Ed), Advances in Imaging
and Electron Physics, 139 (2006)
"""
if a.ndim != 2 or a.shape[0] != a.shape[1] + 1:
raise ValueError("Input must be an (n+1) row x n column, 2-D array")
ai = a.copy()[:-1]
n = ai.shape[1]
f = np.empty((n, n), np.uint32)
f[0] = ai.sum(axis=0)
for m in range(1, n):
# Rolls the pth row of ai right by p places.
for row in range(1, ai.shape[0]):
ai[row] = roll(ai[row], row)
f[m] = ai.sum(axis=0)
f += a[-1][newaxis].T
f = (f - ai[0].sum()) / n
return f