def test_thinPlateSplineApproximate(): """ Asserts that the computed K, P, L and V matrices are formed correctly. Refer to: Bookstein, F. L. (1989). Principal warps: thin-plate splines and the decomposition of deformations. IEEE Transactions on Pattern Analysis and Machine Intelligence, 11(6), 567-585. """ # Form a dummy coordinate class. coords = register.Coordinates([0, 100, 0, 100]) # Form corresponding feature sets. p0 = np.array([0, 1, -1, 0, 0, -1, 1, 0]).reshape(4, 2) p1 = np.array([0, 0.75, -1, 0.25, 0, -1.25, 1, 0.25]).reshape(4, 2) spline = model.ThinPlateSpline(coords) _parameters, _error, L = spline.fit(p0, p1, lmatrix=True) # This expected L matrix is derived from the symmetric example in the # referenced paper. expectedL = np.array([[0., -1.3863, -5.5452, -1.3863, 1., 0., 1.], [-1.3863, 0., -1.3863, -5.5452, 1., -1., 0.], [-5.5452, -1.3863, 0., -1.3863, 1., 0., -1.], [-1.3863, -5.5452, -1.3863, 0., 1., 1., 0.], [1., 1., 1., 1., 0., 0., 0.], [0., -1., 0., 1., 0., 0., 0.], [1., 0., -1., 0., 0., 0., 0.]]) assert np.allclose(L, expectedL), \ "The expected L matrix was not derived."
def warp(image, p, model, sampler): """ Warps an image. """ coords = register.Coordinates([0, image.shape[0], 0, image.shape[1]]) model = model(coords) sampler = sampler(coords) return sampler.f(image, model.warp(p)).reshape(image.shape)
def warp(image): """ Randomly warps an input image using a cubic spline deformation. """ coords = register.Coordinates([0, image.shape[0], 0, image.shape[1]]) spline_model = model.CubicSpline(coords) spline_sampler = sampler.Spline(coords) p = spline_model.identity #TODO: Understand the effect of parameter magnitude: p += np.random.rand(p.shape[0]) * 100 - 50 return spline_sampler.f(image, spline_model.warp(p)).reshape(image.shape)
def warp(image): """ Randomly warps an input image using a projective deformation. """ coords = register.Coordinates([0, image.shape[0], 0, image.shape[1]]) mymodel = model.Projective(coords) mysampler = sampler.CubicConvolution(coords) p = mymodel.identity #TODO: Understand the effect of parameter magnitude: p += np.random.rand(p.shape[0]) * 0.1 - 0.05 return mysampler.f(image, mymodel.warp(p)).reshape(image.shape)
def test_thinPlateSpline(): """ Asserts that the feature point alignment error is sufficiently small. """ # Form a dummy coordinate class. coords = register.Coordinates([0, 10, 0, 10]) # Form corresponding feature sets. p0 = np.array([0, 1, -1, 0, 0, -1, 1, 0]).reshape(4, 2) p1 = np.array([0, 0.75, -1, 0.25, 0, -1.25, 1, 0.25]).reshape(4, 2) spline = model.ThinPlateSpline(coords) _parameters, error = spline.fit(p0, p1) # Assert that the alignment error is small. assert error < 1.0, "Unexpected large alignment error."
def test_affine(): """ Asserts that the feature point alignment error is sufficiently small. """ # Form a dummy coordinate class. coords = register.Coordinates([0, 10, 0, 10]) # Form corresponding feature sets. p0 = np.array([0, 0, 0, 1, 1, 0, 1, 1]).reshape(4, 2) p1 = p0 + 2.0 affine = model.Affine(coords) _parameters, error = affine.fit(p0, p1) # Assert that the alignment error is small. assert error <= 1.0, "Unexpected large alignment error : {} grid units".format( error)
def test_sampler(): """ Asserts that NN < Bilinear < Cubic < Spline, over a range of image resolutions. If (one day) something really amazing happens and the scipy map_coordiantes method is significantly faster we could favour that as a default. """ for n in range(128, 1024, 128): coords = register.Coordinates( [0, n, 0, n] ) img = np.random.rand(n,n) warp = np.random.rand(2,n,n) # nearest neighbour sampler - ctypes nearest = sampler.Nearest(coords) ntimes = np.zeros(10) for i in range(0,10): t1 = time.time() nearest.f(img, warp) t2 = time.time() ntimes[i] = (t2-t1)*1000.0 print 'Nearest : {0}x{0} image - {1:0.3f} ms'.format(n, np.average(ntimes)) # cubic convolution sampler - ctypes bilinear = sampler.Bilinear(coords) btimes = np.zeros(10) for i in range(0,10): t1 = time.time() bilinear.f(img, warp) t2 = time.time() btimes[i] = (t2-t1)*1000.0 print 'Bilinear : {0}x{0} image - {1:0.3f} ms'.format(n, np.average(btimes)) # cubic convolution sampler - ctypes cubic = sampler.CubicConvolution(coords) ctimes = np.zeros(10) for i in range(0,10): t1 = time.time() cubic.f(img, warp) t2 = time.time() ctimes[i] = (t2-t1)*1000.0 print 'Cubic : {0}x{0} image - {1:0.3f} ms'.format(n, np.average(ctimes)) # spline sampler - scipy buffered? ctypes? spline = sampler.Spline(coords) stimes = np.zeros(10) for i in range(0,10): t1 = time.time() spline.f(img, warp) t2 = time.time() stimes[i] = (t2-t1)*1000.0 print 'Spline : {0}x{0} image - {1:0.3f} ms'.format(n, np.average(stimes)) print '====================================' assert np.average(ntimes) < np.average(ctimes) assert np.average(ntimes) < np.average(btimes) assert np.average(ntimes) < np.average(stimes) assert np.average(btimes) < np.average(ctimes) assert np.average(ctimes) < np.average(stimes)