def cog(im): """ Calculate center of gravity (x, y), in world coordinates. """ sampling = tuple(reversed(im.sampling)) grids = pirt.meshgrid(im) total_weight = im.sum() return PointSet([sampling[i] * (grids[i] * im).sum() / total_weight for i in range(len(grids))])
def get_data_big_deform(): """ Create an image with a block if white pixels and two deforms, one to move it down, and another to move it right, in the form of a field and a pointset. """ # Create test image im0 = np.zeros((100, 100), np.float32) im0 = pirt.Aarray(im0, (0.25, 2.0)) im0[30:40, 40:50] = 1.0 c0 = cog(im0) # Create test deformation fields - 50 px down and 40 px right dfield1 = np.zeros((100, 100), np.float32), np.zeros((100, 100), np.float32) weight1 = np.zeros((100, 100), np.float32) dfield1[0][35+50, 45] = -50 * im0.sampling[0] # because backward, correct for sampling weight1[35+50, 45] = 1 # dfield2 = np.zeros((100, 100), np.float32), np.zeros((100, 100), np.float32) weight2 = np.zeros((100, 100), np.float32) dfield2[1][85, 45+40] = -40 * im0.sampling[1] weight2[85, 45+40] = 1 # Create test deformation pointsets - 50 px down and 40 px right pp1, pp2, pp3 = PointSet(2), PointSet(2), PointSet(2) pp1.append(45, 35) # begin pos pp2.append(45, 85) # intermediate pp3.append(85, 85) # end pos for pp in (pp1, pp2, pp3): pp[:] *= PointSet(reversed(im0.sampling)) return im0, c0, dfield1, weight1, dfield2, weight2, pp1, pp2, pp3
def fit_lq1(pp): """ fit_lq1(points) -> t_max, [a,b,c] Fit quadratic polynom to three points in 1D. If more than three points are given, the result is the least squares solution. points can be a 2D ndarray object, resulting in a general solution. If only 3 values are given (as list of numpy array), the point locations are assumed at t=(-1,0,1). """ if isinstance(pp, np.ndarray) and pp.ndim == 2: # Arbitraty position of values. Apply general approach # Prepare A A = PointSet(3) for x in pp[:, 0]: A.append(x**2, x, 1) Ai = scipy.linalg.pinv(np.matrix(A)) # Prepare B B = np.matrix(pp[:, 1]) # Solve X = Ai * B.T # Find extreme P = X.A.ravel().tolist() x = -0.5 * P[1] / P[0] # Done return x, P else: # Values defined at fixed positions (-1,0,1) # Make suitable form multiplication B = np.matrix(pp[0:3]).transpose() # Solve X = _precalculated_Ai1 * B # Find extreme P = X.A.ravel().tolist() x = -0.5 * P[1] / P[0] # done return x, P
from pirt import PointSet, Aarray from pirt import fitting vv.figure(1) vv.clf() ## 1D # Input and result pp = [2, 4, 3] t_max, polynom = fitting.fit_lq1(pp) # Sample polynom polypp = PointSet(2) for i in np.linspace(-1,1,100): polypp.append(i, polynom[0]*i**2 + polynom[1]*i + polynom[2]) # Visualize vv.subplot(121) vv.plot([-1,0,1],pp) vv.plot([t_max, t_max], [0,1], lc='r') vv.plot(polypp, lc='r') ## 2D # Input and result im = vv.imread('astronaut.png')[::,::,2].copy()
(each with a support of 3) results in two different polynoms, which are best combined by linear interpolation. The result is a cubic cardinal spline! To me, this suggests that the Cardinal spline (with tension 0) is the most "natural" cubic spline. """ import numpy as np import visvis as vv import pirt from pirt import PointSet # Input pp = [2, 4, 3, 1] # Interpolate1 res1 = PointSet(2) for t in np.arange(0, 1, 0.01): c_1 = 0.5 * t**2 - 0.5 * t c0 = -t**2 + 1 c1 = 0.5 * t**2 + 0.5 * t res1.append(t, c_1 * pp[0] + c0 * pp[1] + c1 * pp[2]) # Interpolate2 res2 = PointSet(2) for t in np.arange(0, 1, 0.01): c0 = 0.5 * t**2 - 1.5 * t + 1 c1 = -t**2 + 2 * t c2 = 0.5 * t**2 - 0.5 * t res2.append(t, c0 * pp[1] + c1 * pp[2] + c2 * pp[3]) # Linearly combine
INJECTIVE = True FREEZE_EDGES = True # Create test image with one block in the corner im0 = np.zeros((100, 100), np.float32) im0 = Aarray(im0, (0.66, 1.0)) im0[30:40, 40:50] = 1.0 # Draw a grid on it grid_step = 10 im0[1::grid_step,:] = 0.3 im0[:,1::grid_step] = 0.3 # Define three locations, to move the block between pp = PointSet(2) pp.append(45, 35) pp.append(45, 85) pp.append(85, 85) pp = pp * PointSet(reversed(im0.sampling)) # Get down-deformation and right-deformation from_points_multiscale = DeformationFieldBackward.from_points_multiscale deform1 = from_points_multiscale(im0, 4, pp[0:1], pp[1:2], injective=INJECTIVE, frozenedge=FREEZE_EDGES) deform2 = from_points_multiscale(im0, 4, pp[1:2], pp[2:3], injective=INJECTIVE, frozenedge=FREEZE_EDGES) # Combine the two, by composition, not by addition!
Illustrate 2D slicing a 3D volume. The point given to SliceInVolume can also be a 3-element tuple or a visvis.Point. """ import imageio import visvis as vv import pirt from pirt import PointSet # Load volume and get z position of slice 100 vol = imageio.volread('imageio:stent.npz') z100 = 100 # Get three slices representations. The latter two relative to the first, # at the same slice, but oriented differently slice1 = pirt.SliceInVolume(PointSet((64,64,100))) slice2 = pirt.SliceInVolume(PointSet((66,65,106)), previous=slice1) slice3 = pirt.SliceInVolume(PointSet((68,67,106)), previous=slice1) # Show the slices they represent, plus the raw slice at z=100 fig = vv.figure(1); vv.clf() vv.subplot(221); vv.imshow(vol[z100,:,:]) vv.subplot(222); vv.imshow(slice1.get_slice(vol, 128, 0.5)) vv.subplot(223); vv.imshow(slice2.get_slice(vol, 128, 0.5)) vv.subplot(224); vv.imshow(slice3.get_slice(vol, 128, 0.5)) vv.use().Run()
def test_spline_grid_3D_anisotropic(): sg = SplineGrid(FD((90, 90, 90), (2.0, 3.0, 0.5)), 4) # field and sampling # Test basic params assert sg.ndim == 3 assert sg.field_shape == (90, 90, 90) assert sg.field_sampling == (2.0, 3.0, 0.5) assert sg.grid_sampling == 4 assert sg.grid_sampling_in_pixels == (4 / 2.0, 4 / 3.0, 4 / 0.5) assert sg.knots.shape == (48, 70, 15 ) # ceil(90/4) == 23. Add 3 (2 left, 1 right) # Get field, should be empty field = sg.get_field() assert field.shape == sg.field_shape assert np.all(field == 0) # From a field im = 4 * np.ones((20, 20, 20), np.float32) im[4, 5, 5] = 8 im[8, 9, 9] = 7 im = Aarray(im, (2.0, 3.0, 0.5)) sg = SplineGrid.from_field(im, 2) field1 = sg.get_field() assert field1.ndim == 3 assert field1.max() > 5.5 assert field1.max() < 7.5 assert field1.min() > 4 assert field1.min() < 4.7 # From a weighted field im = 4 * np.ones((20, 20, 20), np.float32) im[4, 5, 5] = 8 im[8, 9, 9] = 7 ww = np.zeros((20, 20, 20), np.float32) ww[4, 5, 5] = 1 ww[8, 9, 9] = 1 im = Aarray(im, (2.0, 3.0, 0.5)) sg = SplineGrid.from_field(im, 2, ww) field2 = sg.get_field() assert field2.ndim == 3 assert field2.max() > 7.5 assert field2.max() < 8.5 assert field2.min() >= 0 assert field2.min() < 0.5 # From a weighted field, multiscale im = 4 * np.ones((20, 20, 20), np.float32) im[4, 5, 5] = 8 im[8, 9, 9] = 7 ww = np.zeros((20, 20, 20), np.float32) ww[4, 5, 5] = 1 ww[8, 9, 9] = 1 im = Aarray(im, (2.0, 3.0, 0.5)) sg = SplineGrid.from_field_multiscale(im, 2, ww) field3 = sg.get_field() assert field3.ndim == 3 assert field3.max() > 7.5 assert field3.max() < 8.5 assert field3.min() > 4.5 assert field3.min() < 7 # From points pp = PointSet(3) pp.append(5, 5, 4) pp.append(9, 9, 8) pp2 = pp * PointSet((0.5, 3.0, 2.0)) sg2 = SplineGrid.from_points(FD((20, 20, 20), (2.0, 3.0, 0.5)), 2, pp2, [8, 7]) field5 = sg2.get_field() assert np.all(field5 == field2) # From points, multiscale pp = PointSet(3) pp.append(5, 5, 4) pp.append(9, 9, 8) pp2 = pp * PointSet((0.5, 3.0, 2.0)) sg = SplineGrid.from_points_multiscale(FD((20, 20, 20), (2.0, 3.0, 0.5)), 2, pp2, [8, 7]) field6 = sg.get_field() assert np.all(field6 == field3) # Get field in points values = sg.get_field_in_points(pp2) assert list(values) == [ field6[int(p[0, 2]), int(p[0, 1]), int(p[0, 0])] for p in pp ] # Get field in samples, x-y-z order values2 = sg.get_field_in_samples((pp[:, 2], pp[:, 1], pp[:, 0])) assert list(values) != list(values2) values2 = sg.get_field_in_samples((pp[:, 0], pp[:, 1], pp[:, 2])) assert list(values) == list(values2) # Test copy sg2 = sg.copy() assert sg2.field_shape == sg.field_shape assert sg2.field_sampling == sg.field_sampling assert sg2.grid_sampling == sg.grid_sampling assert sg2.grid_sampling_in_pixels == sg.grid_sampling_in_pixels assert sg2.knots is not sg.knots # Test refine sg2 = sg.refine() assert sg2.field_shape == sg.field_shape assert sg2.field_sampling == sg.field_sampling assert sg2.grid_sampling == sg.grid_sampling / 2 assert sg2.grid_sampling_in_pixels == tuple( [i / 2 for i in sg.grid_sampling_in_pixels]) # Test resize_field sg2 = sg.resize_field(FD((50, 50, 50))) assert sg2.get_field().shape == (50, 50, 50) # Test addition sg2 = sg.add(sg.add(sg)) field = sg2.get_field() assert np.allclose(field, field6 * 3) print('test_spline_grid_3D_anisotropic ok')
def test_spline_grid_1D(): sg = SplineGrid(FD((90, )), 4) # field and sampling # Test basic params assert sg.ndim == 1 assert sg.field_shape == (90, ) assert sg.field_sampling == (1, ) assert sg.grid_sampling == 4 assert sg.grid_sampling_in_pixels == (4, ) assert sg.knots.shape == (26, ) # ceil(90/4) == 23. Add 3 (2 left, 1 right) # Get field, should be empty field = sg.get_field() assert field.shape == sg.field_shape assert np.all(field == 0) # From a field im = np.array([4, 4, 4, 4, 8, 4, 4, 4, 4, 7, 4, 4, 4, 4], np.float32) sg = SplineGrid.from_field(im, 2) field1 = sg.get_field() assert field1.max() > 6 assert field1.max() < 7 assert field1.min() > 4 assert field1.min() < 4.2 # From a weighted field im = np.array([4, 4, 4, 4, 8, 4, 4, 4, 4, 7, 4, 4, 4, 4], np.float32) ww = np.array([0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0], np.float32) sg = SplineGrid.from_field(im, 2, ww) field2 = sg.get_field() assert field2.max() > 7.5 assert field2.max() < 8.5 assert field2.min() > 0 assert field2.min() < 0.5 # From a weighted field, multiscale im = np.array([4, 4, 4, 4, 8, 4, 4, 4, 4, 7, 4, 4, 4, 4], np.float32) ww = np.array([0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0], np.float32) sg = SplineGrid.from_field_multiscale(im, 2, ww) field3 = sg.get_field() assert field3.max() > 7.5 assert field3.max() < 8.5 assert field3.min() > 6 assert field3.min() < 7 # From points pp = PointSet(1) pp.append(4) pp.append(9) sg = SplineGrid.from_points(FD((14, )), 2, pp, [8, 7]) field5 = sg.get_field() assert all(field5 == field2) # From points, multiscale pp = PointSet(1) pp.append(4) pp.append(9) sg = SplineGrid.from_points_multiscale(FD((14, )), 2, pp, [8, 7]) field6 = sg.get_field() assert all(field6 == field3) # Get field in points values = sg.get_field_in_points(pp) assert list(values) == [field6[int(p[0])] for p in pp] # Test copy sg2 = sg.copy() assert sg2.field_shape == sg.field_shape assert sg2.field_sampling == sg.field_sampling assert sg2.grid_sampling == sg.grid_sampling assert sg2.grid_sampling_in_pixels == sg.grid_sampling_in_pixels assert sg2.knots is not sg.knots # Test refine sg2 = sg.refine() assert sg2.field_shape == sg.field_shape assert sg2.field_sampling == sg.field_sampling assert sg2.grid_sampling == sg.grid_sampling / 2 assert sg2.grid_sampling_in_pixels == tuple( [i / 2 for i in sg.grid_sampling_in_pixels]) # Test resize_field sg2 = sg.resize_field(FD((50, ))) assert sg2.get_field().shape == (50, ) # Test addition sg2 = sg.add(sg.add(sg)) field = sg2.get_field() assert np.allclose(field, field6 * 3) print('test_spline_grid_1D ok')
def test_spline_grid_1D_anisotropic(): sg = SplineGrid(FD((90, ), (0.5, )), 4) # field and sampling # Test basic params assert sg.ndim == 1 assert sg.field_shape == (90, ) assert sg.field_sampling == (0.5, ) assert sg.grid_sampling == 4 assert sg.grid_sampling_in_pixels == (8, ) assert sg.knots.shape == (15, ) # Get field, should be empty field = sg.get_field() assert field.shape == sg.field_shape assert np.all(field == 0) # From a field im = np.array([4, 4, 4, 4, 8, 4, 4, 4, 4, 7, 4, 4, 4, 4], np.float32) im = Aarray(im, (0.5, )) sg = SplineGrid.from_field(im, 2) field1 = sg.get_field() assert field1.max() > 5.5 assert field1.max() < 7 assert field1.min() > 4 assert field1.min() < 4.2 # From a weighted field im = np.array([4, 4, 4, 4, 8, 4, 4, 4, 4, 7, 4, 4, 4, 4], np.float32) ww = np.array([0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0], np.float32) im = Aarray(im, (0.5, )) sg = SplineGrid.from_field(im, 2, ww) field2 = sg.get_field() assert field2.max() > 7.5 assert field2.max() < 9.5 assert field2.min() > 0 assert field2.min() < 3.5 # From a weighted field, multiscale im = np.array([4, 4, 4, 4, 8, 4, 4, 4, 4, 7, 4, 4, 4, 4], np.float32) ww = np.array([0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0], np.float32) im = Aarray(im, (0.5, )) sg = SplineGrid.from_field_multiscale(im, 2, ww) field3 = sg.get_field() assert field3.max() > 7.5 assert field3.max() < 8.5 assert field3.min() > 6 assert field3.min() < 7 # From points pp = PointSet(1) pp.append(4) pp.append(9) pp2 = pp * PointSet((0.5, )) sg = SplineGrid.from_points(FD((14, ), (0.5, )), 2, pp2, [8, 7]) field5 = sg.get_field() assert all(field5 == field2) # From points, multiscale pp = PointSet(1) pp.append(4) pp.append(9) pp2 = pp * PointSet((0.5, )) sg = SplineGrid.from_points_multiscale(FD((14, ), (0.5, )), 2, pp2, [8, 7]) field6 = sg.get_field() assert all(field6 == field3) # Get field in points, note pp2, which is in world coords values = sg.get_field_in_points(pp2) assert list(values) == [field6[int(p[0])] for p in pp] # Get field in samples values2 = sg.get_field_in_samples((pp[:, 0], )) assert list(values) == list(values2) # Test copy sg2 = sg.copy() assert sg2.field_shape == sg.field_shape assert sg2.field_sampling == sg.field_sampling assert sg2.grid_sampling == sg.grid_sampling assert sg2.grid_sampling_in_pixels == sg.grid_sampling_in_pixels assert sg2.knots is not sg.knots # Test refine sg2 = sg.refine() assert sg2.field_shape == sg.field_shape assert sg2.field_sampling == sg.field_sampling assert sg2.grid_sampling == sg.grid_sampling / 2 assert sg2.grid_sampling_in_pixels == tuple( [i / 2 for i in sg.grid_sampling_in_pixels]) # Test resize_field sg2 = sg.resize_field(FD((50, ))) assert sg2.get_field().shape == (50, ) # Test addition sg2 = sg.add(sg.add(sg)) field = sg2.get_field() assert np.allclose(field, field6 * 3) print('test_spline_grid_1D_anisotropic ok')
def test_spline_grid_2D(): sg = SplineGrid(FD((90, 90)), 4) # field and sampling # Test basic params assert sg.ndim == 2 assert sg.field_shape == (90, 90) assert sg.field_sampling == (1, 1) assert sg.grid_sampling == 4 assert sg.grid_sampling_in_pixels == (4, 4) assert sg.knots.shape == (26, 26 ) # ceil(90/4) == 23. Add 3 (2 left, 1 right) # Get field, should be empty field = sg.get_field() assert field.shape == sg.field_shape assert np.all(field == 0) # From a field im = 4 * np.ones((20, 20), np.float32) im[4, 5] = 8 im[8, 9] = 7 sg = SplineGrid.from_field(im, 2) field1 = sg.get_field() assert field1.ndim == 2 assert field1.max() > 5.5 assert field1.max() < 6.5 assert field1.min() > 4 assert field1.min() < 4.5 # From a weighted field im = 4 * np.ones((20, 20), np.float32) im[4, 5] = 8 im[8, 9] = 7 ww = np.zeros((20, 20), np.float32) ww[4, 5] = 1 ww[8, 9] = 1 sg = SplineGrid.from_field(im, 2, ww) field2 = sg.get_field() assert field2.ndim == 2 assert field2.max() > 7.5 assert field2.max() < 8.5 assert field2.min() >= 0 assert field2.min() < 0.5 # From a weighted field, multiscale im = 4 * np.ones((20, 20), np.float32) im[4, 5] = 8 im[8, 9] = 7 ww = np.zeros((20, 20), np.float32) ww[4, 5] = 1 ww[8, 9] = 1 sg = SplineGrid.from_field_multiscale(im, 2, ww) field3 = sg.get_field() assert field3.ndim == 2 assert field3.max() > 7.5 assert field3.max() < 8.5 assert field3.min() > 5 assert field3.min() < 7 # From points pp = PointSet(2) pp.append(5, 4) pp.append(9, 8) sg2 = SplineGrid.from_points(FD((20, 20)), 2, pp, [8, 7]) field5 = sg2.get_field() assert np.all(field5 == field2) # From points, multiscale pp = PointSet(2) pp.append(5, 4) pp.append(9, 8) sg = SplineGrid.from_points_multiscale(FD((20, 20)), 2, pp, [8, 7]) field6 = sg.get_field() assert np.all(field6 == field3) # Get field in points values = sg.get_field_in_points(pp) assert list(values) == [field6[int(p[0, 1]), int(p[0, 0])] for p in pp] # Get field in points beyond field pp = PointSet(2) pp.append(100, 103) pp.append(-100, -108) values = sg.get_field_in_points(pp) assert list(values) == [field6[int(p[0, 1]), int(p[0, 0])] for p in pp] # Test copy sg2 = sg.copy() assert sg2.field_shape == sg.field_shape assert sg2.field_sampling == sg.field_sampling assert sg2.grid_sampling == sg.grid_sampling assert sg2.grid_sampling_in_pixels == sg.grid_sampling_in_pixels assert sg2.knots is not sg.knots # Test refine sg2 = sg.refine() assert sg2.field_shape == sg.field_shape assert sg2.field_sampling == sg.field_sampling assert sg2.grid_sampling == sg.grid_sampling / 2 assert sg2.grid_sampling_in_pixels == tuple( [i / 2 for i in sg.grid_sampling_in_pixels]) # Test resize_field sg2 = sg.resize_field(FD((50, 50))) assert sg2.get_field().shape == (50, 50) # Test addition sg2 = sg.add(sg.add(sg)) field = sg2.get_field() assert np.allclose(field, field6 * 3) print('test_spline_grid_2D ok')
def test_deformation_grid_multiscale(): """ Multiscale, so that we can get the actual deformation, but keep in mind that DeformationField.from_xxx() are to be preferred because they care about injectivity and composition. """ im0, c0, dfield1, weight1, dfield2, weight2, pp1, pp2, pp3 = get_data_big_deform() # Shift down # Shift down using deformation as field d4 = DeformationGridBackward.from_field_multiscale(dfield1, 4, weight1, fd=im0) assert d4.field_sampling == im0.sampling for grid in d4.grids: assert grid.field_sampling == im0.sampling assert grid.grid_sampling == 4 # Shift down using deformation as points d5 = DeformationGridBackward.from_points_multiscale(im0, 4, pp1, pp2) assert d5.field_sampling == im0.sampling for grid in d5.grids: assert grid.field_sampling == im0.sampling assert grid.grid_sampling == 4 # Test that d4 and d5 are equal, so further tests can be combined for d in range(d4.ndim): assert np.all(d4.get_field(d) == d5.get_field(d)) # Assert that the deform shifts down im4 = d4.apply_deformation(im0) c4 = cog(im4) assert c4.distance(c0 + PointSet((0, 50 * im0.sampling[0]))) < 1 # Shift right # Create deforms d6 = DeformationGridBackward.from_field_multiscale(dfield2, 4, weight2, fd=im0) d7 = DeformationGridBackward.from_points_multiscale(im0, 4, pp2, pp3) # Test that d6 and d7 are equal, so further tests can be combined for d in range(d6.ndim): assert np.all(d6.get_field(d) == d7.get_field(d)) # Shift the original image to the right, works because whole image is shifted im6 = d6.apply_deformation(im0) c6 = cog(im6) assert c6.distance(c0 + PointSet((40 * im0.sampling[1], 0))) < 1 # Shift down-shifted image to right im6 = d6.apply_deformation(im4) c6 = cog(im6) assert c6.distance(c0 + PointSet((40 * im0.sampling[1], 50 * im0.sampling[0]))) < 1 # Combine deforms in wrong way, but result is still pretty good because deform is near-uniform d7 = d4 + d6 im7 = d7.apply_deformation(im0) assert not np.allclose(im7, im6, atol=1) # Compising is much better! d8 = d4.compose(d6) im8 = d8.apply_deformation(im0) assert np.allclose(im8, im6, atol=0.01) # vv.figure(1); vv.clf(); vv.subplot(221); vv.imshow(im0); vv.subplot(222); vv.imshow(im6); vv.subplot(223); vv.imshow(im7); vv.subplot(224); vv.imshow(im8) print('deformation_grid_multiscale ok')
""" import numpy as np import visvis as vv from pirt import PointSet, SplineGrid # Read image im = vv.imread('astronaut.png').astype(np.float32) im_r = im[:, :, 0] # New sparse image and interpolated image ims = np.zeros_like(im) imi = np.zeros_like(im) # Select points from the image pp = PointSet(2) R, G, B = [], [], [] for i in range(10000): y = np.random.randint(0, im.shape[0]) x = np.random.randint(0, im.shape[1]) pp.append(x, y) R.append(im[y, x, 0]) G.append(im[y, x, 1]) B.append(im[y, x, 2]) ims[y, x] = im[y, x] # Make three grids spacing = 10 grid1 = SplineGrid(im_r, spacing) grid2 = SplineGrid(im_r, spacing) grid3 = SplineGrid(im_r, spacing)