Subdivision Curves
Subdvision methods progressively refine a discrete curve and converge to a smooth curve. This allows to perform an interpolation or approximation of a given coarse dataset.
Contents
Installing toolboxes and setting up the path.
You need to download the following files: signal toolbox, general toolbox, graph toolbox and wavelet_meshes toolbox.
You need to unzip these toolboxes in your working directory, so that you have toolbox_signal, toolbox_general, toolbox_graph and toolbox_wavelet_meshes in your directory.
For Scilab user: you must replace the Matlab comment '%' by its Scilab counterpart '//'.
Recommandation: You should create a text file named for instance numericaltour.sce (in Scilab) or numericaltour.m (in Matlab) to write all the Scilab/Matlab command you want to execute. Then, simply run exec('numericaltour.sce'); (in Scilab) or numericaltour; (in Matlab) to run the commands.
Execute this line only if you are using Matlab.
getd = @(p)path(p,path); % scilab users must *not* execute this
Then you can add the toolboxes to the path.
getd('toolbox_signal/'); getd('toolbox_general/'); getd('toolbox_graph/'); getd('toolbox_wavelet_meshes/');
Curve Subdivision
Starting from an initial set of control points (which can be seen as a coarse curve), subdivision produces a smooth 2D curve.
In the following, a 2D curve is discretized as a vector of complex numbers.
Define the low pass filter (subdivision kernel). It should sum to 2.
h = [1 4 6 4 1]; h = 2*h/sum(h(:));
Define the initial coarse set of control points.
f0 = [0.11 0.18 0.26 0.36 0.59 0.64 0.80 0.89 0.58 0.22 0.18 0.30 0.58 0.43 0.42]' + ...
1i * [0.91 0.55 0.91 0.58 0.78 0.51 0.81 0.56 0.10 0.16 0.35 0.42 0.40 0.24 0.31]';
Rescale it to fit in a box.
f0 = rescale(real(f0),.01,.99) + 1i * rescale(imag(f0),.01,.99);
Initilize the subdivision.
f = f0;
One step of subdivision correspond to a step of inverse wavelet transform (applied to each X/Y channel of f0) but with vanishing wavelet coefficients.
First upsample each channel, which corresponds to inserting zeros. The filter using a circular convolution.
f = cconv( upsampling(f), h);
Display the original and filtered discrete curves.
ms = 20; lw = 1.5; hold on; hh = plot(f([1:end 1]), 'k.-'); set(hh, 'MarkerSize', ms); set(hh, 'LineWidth', lw); hh = plot(f0([1:end 1]), 'r.--'); set(hh, 'LineWidth', lw); axis([0 1 0 1]); axis off;
Exercice 1: (the solution is exo1.m) Perform several step of subdivision. Display the different curves.
exo1;
Exercice 2: (the solution is exo2.m) Compute the scaling function (interpolation kernel) associated to the subdivision. Here this is a cubic B-spline interpolation.
exo2;
Exercice 3: (the solution is exo3.m) Test with different configuration of control points.
exo3;
Exercice 4: (the solution is exo4.m) Try with different filters h. Here we use h=[1 3 3 1]/4, which corresponds to the famous Chaikin "corner cutting" scheme. This corresponds to a quadratic B-spline interpolation.
exo4;
Interpolating Subdivision
Interpolating schemes keeps unchange the set of point at the previous level, and only smooth the position of the added points.
It means that the filter h should satisfies h(0)=1 and h(2k)=0 for all non zero k.
This is a filter proposed by Dyn, Levin and Gregory.
h = [-1, 0, 9, 1, 9, 0, -1]/16; h((end+1)/2)=1;
Exercice 5: (the solution is exo5.m) Perform the interpolating subdivision.
exo5;
Exercice 6: (the solution is exo6.m) Compare the result of the quadratic B-spline, cubic B-spline, and Dyn Levin Gregory.
exo6;
Curve Approximation
Given an input, complicated curve, it is possible to approximate is by sampling the curve, and then
Load an initial random curve.
options.bound = 'per';
n = 1024*2;
sigma = n/8;
F = perform_blurring(randn(n,1),sigma,options) + 1i*perform_blurring(randn(n,1),sigma,options);
F = rescale(real(F),.01,.99) + 1i * rescale(imag(F),.01,.99);
Display it.
clf; hh = plot(F([1:end end]), 'k'); set(hh, 'LineWidth', lw); axis([0 1 0 1]);
Load an interpolating subvision mask.
h = [-1, 0, 9, 1, 9, 0, -1]/16; h((end+1)/2)=1;
Exercice 7: (the solution is exo7.m) Perform an approximation f of the curve using a uniform sampling with 20 points.
exo7;
To quantify the quality of the approximation, we use the L2 Hausdorff distance.
Compute the pairwise distances between points.
D = abs( repmat(F, [1 length(f)]) - repmat(transpose(f), [length(F) 1]) );
Compute the Hausdorff distance.
d = sqrt( ( mean(min(D).^2) + mean(min(D').^2) )/2 );
disp(['Hausdorff distance: ' num2str(d, 3)]);
Hausdorff distance: 0.00943
Exercice 8: (the solution is exo8.m) Display the decay of the Hausdorff approximation error as the number of sampling points increases.
exo8;
Exercice 9: (the solution is exo9.m) Perform an optimization of the position of the points to minimize the Hausdorff approximation error.
exo9;
Exercice 10: (the solution is exo10.m) Test on other curves.
exo10;
3D Curve Subdivision
It is possible to construct 3D curves by subdivision.
Exercice 11: (the solution is exo11.m) Perform curve subdivision in 3D space.
exo11;