Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

some question about B-spline kernel matrix #21

Open
MangoWAY opened this issue Dec 26, 2019 · 3 comments
Open

some question about B-spline kernel matrix #21

MangoWAY opened this issue Dec 26, 2019 · 3 comments

Comments

@MangoWAY
Copy link

Hi! I'm studying the source code. I find the method

def bspline_kernel_3d(sigma=[1, 1, 1], order=2, asTensor=False, dtype=th.float32, device='cpu'):
    kernel_ones = th.ones(1, 1, *sigma)
    kernel = kernel_ones
    padding = np.array(sigma) - 1

    for i in range(1, order + 1):
        kernel = F.conv3d(kernel, kernel_ones, padding=(padding).tolist())/(sigma[0]*sigma[1]*sigma[2])
	
    if asTensor:
        return kernel[0, 0, ...].to(dtype=dtype, device=device)
    else:
        return kernel[0, 0, ...].numpy()

I know we can use the control points to control the displacements. I've also read about other
bspline implementations. The airlab bspline method looks like very simple. So I want to know how does it work, the meaning of sigma and why the for loop can get the bspline kernel.
Thanks! :)

@cherise215
Copy link

Not sure if my answer is 100 per cent correct or not. But in WIKI it says: 'Fast b-spline interpolation on a uniform sample domain can be done by iterative mean-filtering'. https://en.wikipedia.org/wiki/B-spline. In this case, the initial kernel can be view as a mean-filter, which is then interactively convolved to achieve higher-order interpolation.

@qiuhuaqi
Copy link

qiuhuaqi commented Jun 10, 2020

Just adding some details to @cherise215's answer to explain this implementation:

  • n-th order B-spline function can be computed by recursive convolution with 0-th order B-spline function n times:
    image
    0-th order B-spline function is a rectangle window, which is kernel_one in the code. And sigma is effectively the "width" of this rectangle.

  • Since this rectangle function is symmetrical, convolution between kernel and kernel_one is the same as cross-correlation, which can be implemented using F.convNd() function. By setting padding=sigma-1, only the over-lapping part of the convolution is computed, which is also referred to as the "support" (non-zero part) of B-spline function.

  • You should also expect the size of the kernel getting bigger as the order increases. The kernel size should increase by sigma-1 in each convolution, so output kernel size should be sigma + order*(sigma-1). You can work out the sigma you want from your desired kernel size using this formula.

As an example, 2D quadratic (order=2) B-spline kernel with sigma=[6, 6] (kernel size 16x16) looks like this
image

This implementation allows us to use an arbitrary order of B-spline function, which is pretty neat.

@qiuhuaqi
Copy link

qiuhuaqi commented Jun 10, 2020

A small problem in my opinon is that the transformation model in this implementation doesn't seem to allow flexible combinations of kernel size and control point spacing (stride=sigma in transposed conv), which are both locked by sigma.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants