freeform op• Data kinds: image2d × image2d × image2d → bspline_surface
• Call: import fullseye as fs; fs.ledger.fit_bspline_surface(x, y, z, kx=3, ky=3, smooth=None) (to call the implementation directly, import bspline_surf; bspline_surf.fit_bspline_surface(x, y, z, kx=3, ky=3, smooth=None); from the registry, ops3d.get("fit_bspline_surface"))
Least-squares fit a bicubic (default) B-spline surface to scattered (x, y, z) (bisplrep).
x, y, z : array_like
Scattered sample coordinates and heights of equal count. Any shape is accepted; they are flattened to 1-D internally.
kx, ky : int
B-spline degree in the x/y direction (1=linear, 3=cubic). If the point count is less than (kx+1)*(ky+1)
the degree is lowered automatically (to avoid degeneracy).
smooth : float or None
Smoothing factor s. None is an automatic value based on the point count (_auto_surface_smooth).
0.0 passes through all points (interpolation-like = prone to overfitting); larger is smoother.
tck : list
[tx, ty, c, kx, ky]. Pass to eval_bspline_surface / surface_residual.
ValueError
If there are too few points even for a linear surface (m<4), the lengths of x/y/z differ, there are non-finite values,
or no approximation can be obtained because of FITPACK degeneracy from collinear or duplicate points.
Notes (verified against the implementation):
• The coordinate system is free: x, y are any planar coordinates (row/col or physical units), z is the height. The 3 arrays are flattened to 1-D with ravel, so grid input and scattered input are treated the same.
• Automatic degree lowering decrements the larger degree (kx on a tie) by 1 while (kx+1)*(ky+1) > m, and stops when both are 1. The lowering happens silently rather than as an exception, so check the actual degrees in the returned tck[3], tck[4].
• The automatic value for smooth=None is max(0, m - sqrt(2m)) (FITPACK's recommendation). The formula assumes a z noise variance of about 1, so data with small z units and a small residual sum of squares tend to be oversmoothed. In that case pass a small smooth explicitly.
• FITPACK warnings (iteration cut-off etc.) are swallowed and tck is returned. All exceptions are translated to ValueError, and an empty coefficient set also gives ValueError.
• Deterministic (no randomness).
• Downstream are eval_bspline_surface (evaluation) and surface_residual (deviation). If only global low-order waviness is needed there are fit_poly_surface / eval_poly_surface, but tck and the polynomial dict are not interchangeable.
• Sample-data catalog (download URLs / licences) — 2-D uses skimage.data (BSD/public domain) plus synthetic images; 3-D lists download URLs for real data sources (Stanford, PDS, …).
• Operator provenance and references — the sources of the research/methods this op family came from.
• bspline_freeform — py -3.11 examples_3d/bspline_freeform.py
bspline_surface as input)fuse_to_voxel · eval_bspline_surface · surface_residual
freeform)eval_bspline_surface · surface_residual · fit_bspline_curve · eval_bspline_curve
*Provenance: bspline_surf.py — 3D operator registry. This per-op note is generated by tools/opdocs.py md (do not hand-edit).*
© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.