Skip to content

Commit d18873d

Browse files
committed
Zernike transform prototype
1 parent 9d0041b commit d18873d

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

src/tike/zernike.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def _bino(a: int, b: int) -> int:
7878
return result
7979

8080

81-
def basis(size: int, degree: int) -> np.array:
81+
def basis(size: int, degree_min: int, degree_max: int) -> np.array:
8282
"""Return all circular Zernike basis up to given radial degree.
8383
8484
Parameters
@@ -102,16 +102,16 @@ def basis(size: int, degree: int) -> np.array:
102102
theta = np.arctan2(coords[0], coords[1])
103103

104104
basis = []
105-
for m, n in valid_indices(degree):
105+
for m, n in valid_indices(degree_min, degree_max):
106106
basis.append(Z(m, n, radius, theta))
107107

108108
basis = np.stack(basis, axis=0)
109109
return basis
110110

111111

112-
def valid_indices(degree: int) -> tuple:
112+
def valid_indices(degree_min: int, degree_max: int) -> tuple:
113113
"""Enumerate all valid zernike indices (m,n) up to the given degree."""
114-
for n in range(0, degree):
114+
for n in range(degree_min, degree_max):
115115
for m in range(-n, n + 1):
116116
if (n - abs(m)) % 2 == 0:
117117
yield m, n

tests/data/probe.png

3.17 KB
Loading

tests/test_zernike.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33

44
import tike.zernike
5+
import tike.linalg
56
import tike.view
67
import matplotlib.pyplot as plt
78
import numpy as np
@@ -50,3 +51,47 @@ def test_radial_1(self):
5051

5152
def test_radial_2(self):
5253
self._radial_template(2)
54+
55+
def test_transform(self):
56+
57+
fname = os.path.join(testdir, 'result', 'zernike')
58+
os.makedirs(fname, exist_ok=True)
59+
60+
# import libimage
61+
62+
# f0 = libimage.load('cryptomeria', 256)
63+
f0 = plt.imread(os.path.join(testdir, 'data', 'probe.png'))
64+
size = f0.shape[-1]
65+
plt.imsave(os.path.join(fname, 'basis-0.png'), f0)
66+
67+
f0 = f0.reshape(size * size, 1)
68+
69+
_basis = []
70+
71+
for d in range(0, 100):
72+
_basis.append(
73+
tike.zernike.basis(
74+
size,
75+
degree_min=d,
76+
degree_max=d + 1,
77+
))
78+
79+
basis = np.concatenate(_basis, axis=0)
80+
print(f'degree {d} - {len(basis)}')
81+
basis = np.moveaxis(basis, 0, -1)
82+
basis = basis.reshape(size * size, -1)
83+
# weight only pixels inside basis
84+
w = (basis[..., 0] > 0).astype('float32')
85+
86+
# x = tike.linalg.lstsq(basis, f0, weights=w)
87+
x, _, _, _ = np.linalg.lstsq(basis, f0, rcond=1e-4)
88+
89+
f1 = basis @ x
90+
f1 = f1.reshape(size, size)
91+
plt.imsave(os.path.join(fname, f'basis-{d:02d}.png'), f1)
92+
93+
plt.figure()
94+
plt.title(f"basis weights for {d} degree polynomials")
95+
plt.bar(list(range(x.size)), x.flatten())
96+
plt.savefig(os.path.join(fname, f'basis-w-{d:02d}.png'))
97+
plt.close()

0 commit comments

Comments
 (0)