I am looking for a MATLAB solution to generate the matrix representation of a discrete Radon transform (DRT). That is, given a vectorized version of an MxN image, X, I'd like to generate the matrix R such that R*X(:) is a DRT of the image. In MATLAB, I am expecting it to look something like the following:
>> X = 2D_Image_Of_Size_MxN;
>> R = DRT_Matrix_Of_Size_LPxMN;
>> DRT = reshape( R * X(:), L, P );
I know there are several ways to define a DRT, so I'll just say that I am looking for a normal or standard or not-too-out-of-the-ordinary implmentation.
function [ R rho theta ] = radonmatrix( drho, dtheta, M, N )
% radonmatrix - Discrete Radon Trasnform matrix
%
% SYNOPSIS
% [ R rho theta ] = radonmatrix( drho, dtheta, M, N )
%
% DESCRIPTION
% Returns a matrix representation of a Discrete Radon
% Transform (DRT).
%
% INPUT
% drho Radial spacing the the DRT.
% dtheta Angular spacing of the DRT (rad).
% M Number of rows in the image.
% N Number of columns in the image.
%
% OUTPUT
% R LP x MN DRT matrix. The values of the L and
% P will depend on the radial and angular spacings.
% rho Vector of radial sample locations.
% theta Vector of angular sample locations (rad).
%
% For each angle, we define a set of rays parameterized
% by rho. We then find the pixels on the MxN grid that
% are closest to each line. The elements in R corresponding
% to those pixels are given the value of 1.
% The maximum extent of the region of support. It's for
% rho = 0 and theta = pi/4, the line that runs caddy-corner.
W = sqrt( M^2 + N^2 );
rho = -W/2 : drho : W/2;
theta = 0 : dtheta : 180 - dtheta;
L = length( rho );
P = length( theta );
R = false( L*P, M*N );
% Define a meshgrid w/ (0,0) in the middle that
% we can use a standard coordinate system.
[ mimg nimg ] = imggrid( 1, 1, [ M N ] );
% We loop over each angle and define all of the lines.
% We then just figure out which indices each line goes
% through and put a 1 there.
for ii = 1 : P
phi = theta(ii) * pi/180;
% The equaiton is rho = m * sin(phi) + n * cos(phi).
% We either define a vector for m and solve for n
% or vice versa. We chose which one based on angle
% so that we never g4et close to dividing by zero.
if( phi >= pi/4 && phi <= 3*pi/4 )
t = -W : min( 1/sqrt(2), 1/abs(cot(phi)) ) : +W;
T = length( t );
rhom = repmat( rho(:), 1, T );
tn = repmat( t(:)', L, 1 );
mline = ( rhom - tn * cos(phi) ) ./ sin(phi);
for jj = 1 : L
p = round( tn(jj,:) - min( nimg ) ) + 1;
q = round( mline(jj,:) - min( mimg ) ) + 1;
inds = p >= 1 & p <= N & q >= 1 & q <= M;
R( (ii-1)*L + jj, unique( sub2ind( [ M N ], q(inds), p(inds) ) ) ) = 1;
end
else
t = -W : min( 1/sqrt(2), 1/abs(tan(phi)) ) : +W;
T = length( t );
rhon = repmat( rho(:)', T, 1 );
tm = repmat( t(:), 1, L );
nline = ( rhon - tm * sin(phi) ) ./ cos(phi);
for jj = 1 : L
p = round( nline(:,jj) - min( nimg ) ) + 1;
q = round( tm(:,jj) - min( mimg ) ) + 1;
inds = p >= 1 & p <= N & q >= 1 & q <= M;
R( (ii-1)*L + jj, unique( sub2ind( [ M N ], q(inds), p(inds) ) ) ) = 1;
end
end
end
R = double( sparse( R ) );
return;
Here is the imggrid function used in the above.
function [ m n ] = imggrid( dm, dn, sz )
% imggrid -- Returns rectilinear coordinate vectors
%
% SYNOPSIS
% [ m n ] = imggrid( dm, dn, sz )
%
% DESCRIPTION
% Given the sample spacings and the image size, this
% function returns the row and column coordinate vectors
% for the image. Both vectors are centered about zero.
%
% INPUT
% dm Spacing between rows.
% dn Spacing between columns.
% sz 2x1 vector of the image size: [ Nrows Ncols ].
%
% OUTPUT
% m sz(1) x 1 row coordinate vector.
% n 1 x sz(2) column coordinate vector.
M = sz(1);
N = sz(2);
if( mod( M, 2 ) == 0 )
m = dm * ( ceil( -M/2 ) : floor( M/2 ) - 1 )';
else
m = dm * ( ceil( -M/2 ) : floor( M/2 ) )';
end
if( mod( N, 2 ) == 0 )
n = dn * ( ceil( -N/2 ) : floor( N/2 ) - 1 );
else
n = dn * ( ceil( -N/2 ) : floor( N/2 ) );
end
image = phantom();
projection = radon(image);
R = linsolve(reshape(image,1,[]), reshape(projection,1,[]));
Related
Hi I am looking for some help to optimize some Matlab code. I have an input matrix M, which is Ny rows by Nx columns. I would like to define a boundary all the way round the edge of the matrix where the values should be attenuated smoothly down to zero. To do this, I attempted to define a masking function MSK and multiply it point by point to get an output N, shown below:
My attempt above was created using the code below, where I use a cosine squared function to get the smooth drop off from 1 to zero:
%%% Set up some grids %%%
Nx = 128;
Ny = 64;
dx = 0.1;
dy = 0.1;
x = -(Nx*dx/2):dx:(Nx*dx/2-dx);
y = -(Ny*dy/2):dy:(Ny*dy/2-dy);
x = permute(x, [1 2 3]); % Creates a [1 x Nx x 1] vector (saves memory)
y = permute(y, [2 1 3]); % Creates a [Ny x 1 x 1] vector
M = complex( double( rand(Ny,Nx)+10 ) ); % Create some input data
bnd_frac = 0.7; % The fraction of the grid to begin masking boundary, i.e 70% of the grid max
MSK = create_mask_function(x,y,Nx,Ny,bnd_frac); % Create masking function
N = M.*MSK; % Apply mask to input data, to smoothly ramp edges to zero
figure;
subplot(1,3,1);imagesc(x,y, abs(M) )
subplot(1,3,2);imagesc(x,y, abs(MSK) )
subplot(1,3,3);imagesc(x,y, abs(N) )
%%%%%%%%%%%%%%%%%%%%%%%%
%%% Masking Function %%%
%%%%%%%%%%%%%%%%%%%%%%%%
function MSK = create_mask_function(x,y,Nx,Ny,bnd_frac)
[~,bndind_x] = min( abs(x - bnd_frac*x(Nx)) ); % Find the index to begin the masking
x_bound = x(bndind_x); % Find the grid coordinate to begin masking
[~,bndind_y] = min( abs(y - bnd_frac*y(Ny)) );
y_bound = y(bndind_y);
dbnd_xp = x(Nx) - x_bound; % Find the width of the boundary region at each edge
dbnd_xm = x(1) + x_bound;
dbnd_yp = y(Ny) - y_bound;
dbnd_ym = y(1) + y_bound;
MSK = ones(Ny,Nx); % Initialise the mask matrix as ones
% Set the values within each boundary region at the edge to ramp smoothly to 0 from 1
MSK( : , x > x_bound ) = repmat( ( cos( ( x(x>+x_bound) - x_bound )/dbnd_xp * pi/2 ) ).^2 , Ny , 1);
MSK( : , x < -x_bound ) = repmat( ( cos( ( x(x<-x_bound) + x_bound )/dbnd_xm * pi/2 ) ).^2 , Ny , 1);
MSK( y > y_bound , : ) = repmat( ( cos( ( y(y>+y_bound) - y_bound )/dbnd_yp * pi/2 ) ).^2 , 1 , Nx);
MSK( y < -y_bound , : ) = repmat( ( cos( ( y(y<-y_bound) + y_bound )/dbnd_ym * pi/2 ) ).^2 , 1 , Nx);
MSK(:,Nx,:) = 0;
MSK(:,1,:) = 0;
MSK(Ny,:,:) = 0;
MSK(1,:,:) = 0;
end
The problem with the code above is that it allocates too much memory to MSK.
(In the real version of my code, all of of the matrices are 3D, and the sizes can be more like 1024x512x512 in reality, but I have made a simplifed 2D example here to help explain.)
Note that this is the reason that I am using permute() on the x and y vectors above, because other parts of my full code use Matlab's implicit expansion. This is to avoid storing 3D versions of x and y that have been generated using meshgrid().
It is clear in the above image that MSK contains mostly values of 1, and the ramping values only occur near the edges. So this seems like large waste of memory to store those 1's because their purpose is to just make sure the input matrix is not modified in the centre. Can anyone help me understand a way in Matlab to implement what I want but in a way that will use less RAM?
If you can't store, then you need to recompute the weights each time and use them on the fly.
The short answer then is that instead of some precomputing of MSK and then usage later, as:
MSK( : , x > x_bound ) = repmat( ( cos( ( x(x>+x_bound) - x_bound )/dbnd_xp * pi/2 ) ).^2 , Ny , 1);
etc()
...
N = M.*MSK
You want to just, on the fly:
N( : , x > x_bound ) = M( : , x > x_bound ).*repmat( ( cos( ( x(x>+x_bound) - x_bound )/dbnd_xp * pi/2 ) ).^2 , Ny , 1);
etc()
I'll leave how you restructure the code to you, but I'd basically just add the matrix M as input to your function, and rename it to "apply_mask" or something like that. There will likely be ways to optimize this further if needed, but "early optimization is the root of all evil".
I try to generate the following two matrix within one line (e.g. repmat, reshape) but I can not find a solution:
This is the first matrix
And this is the second matrix:
Edit:
Homework would be fun...background:
I try to implement a simple image resize algorithm. Finally I want use the codegenerator to create the corresponding C code. This is the current implementation:
function [ J ] = resize( I, sc ) %#codegen
% Function implements an algorithm to scale down given image 'I' by factor 'sc':
%
% Input data description:
% I : Grayscale 2-dimensional image
% sc: Image scale factor [-]
% -------------------------------------------------------------------------
assert( isa( I , 'uint8' ) );
assert( isa( sc, 'uint8' ) );
assert( ( sc >= 0 ) && ( sc <= 10 ) );
% Calculate scaled image size [pixel]:
ns = uint8( fix( size( I ) / single( sc ) ) );
nr = ns( 1 );
nc = ns( 2 );
% Number of elements within window:
nw = sc * sc;
% Resulting image:
J = zeros( ns, 'uint8' );
% Create index lookup table to access windows within 'I':
ri = reshape( 1 : sc * nr, sc, nr );
ci = reshape( 1 : sc * nc, sc, nc );
% Loop over image 'I' and calculate mean for each window 'w' of size [sc sc]:
% coder.unroll( );
for c = 1 : nc
% coder.unroll( );
for r = 1 : nr
% Extract window 'I_w' of fixed size [sc sc] from image 'I':
I_w = I( ri( :, r ), ci( :, c ) );
% Calculate mean of window 'I_w':
s = uint16( 0 );
% coder.unroll( );
for i = 1 : nw
s = s + uint16( I_w( i ) );
end
J( r, c ) = s / uint16( nw );
end
end
This works well. With I=[120 160], sc=6 I get:
/* MATLAB Function: '<S4>/Resize' */
for (loop_ub = 0; loop_ub < 26; loop_ub++) {
for (r = 0; r < 20; r++) {
s = 0U;
for (nz = 0; nz < 36; nz++) {
s = (uint16_T)((uint32_T)rtu_I[((ci[loop_ub * 6 + nz / 6] - 1) * 120 +
ri[r * 6 + nz % 6]) - 1] + s);
}
z = (uint16_T)(s / 36U);
s = (uint16_T)((uint32_T)s - (uint16_T)(z * 36U));
if ((s > 0) && (s >= 18)) {
z++;
}
rtb_I_sc[r + 20 * loop_ub] = (uint8_T)z;
}
}
Variables ci, ri are pre- computed by the codegenerator and const arrays within the C code. Nice. Calculating the image index has still a lot overhead:
s = (uint16_T)((uint32_T)rtu_I[((ci[loop_ub * 6 + nz / 6] - 1) * 120 + ri[r * 6 + nz % 6]) - 1] + s);
Now my idea was to pre- compute all required indicies:
% Create index lookup table to access windows within 'I':
% ri = repelem( reshape( 1 : sc * nr, sc, [] ), sc, 1 );
% ri = repmat( ri, 1, nr );
%
% ci = repelem( reshape( 1 : sc * nc, sc, [] ), 1, nc );
% ci = repmat( ci, sc, 1 );
%
% id = sub2ind( size( I ), ri(:), ci(:) );
%
% id = reshape( id, N, [] );
%
% % Loop over image 'I' and calculate mean for each window 'w' of size [sc sc]:
% for c = 1 : nc
% for r = 1 : nr
% % Extract window 'I_w' of fixed size [sc sc] from image 'I':
% I_w = I( id( :, r * c ) );
%
% % Calculate mean of window 'I_w':
% s = uint16( 0 );
% for i = 1 : N
% s = s + uint16( I_w( i ) );
% end
% J( r, c ) = s / uint16( N );
% end
% end
Above code is not working properly at all, but the main issue is that the indicies are not pre-computed. The implementation seems to be too complicate for the code generator. Therefore I was looking for some magic reshape (whatever) commands to setup the lookup tables.
I tried to implement the cost function of the Dual Absolute Quadric in Matlab according to the following equation mentioned in this paper, with this data.
My problem is that the results didn't converge.
The code is down.
main code
%---------------------
% clear and close all
%---------------------
clearvars
close all
clc
%---------------------
% Data type long
%---------------------
format long g
%---------------------
% Read data
%---------------------
load('data.mat')
%---------------------------
% Display The Initial Guess
%---------------------------
disp('=======================================================')
disp('Initial Intrinsic parameters: ');
disp(A);
disp('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
%=========================================================================
DualAbsoluteQuadric = Optimize(A,#DAQ);
%---------------------
% Display The Results
%---------------------
disp('=======================================================')
disp('Dual Absoute Quadric cost function: ');
disp(DualAbsoluteQuadric);
disp('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
The optimization function used is:
function output = Optimize(A,func)
%------------------------------
options = optimoptions('lsqnonlin','Algorithm','levenberg-marquardt',...
'Display','iter','FunctionTolerance',1e-16,'Tolx',1e-16,...
'MaxFunctionEvaluations', 1000, 'MaxIterations',39,...
'OptimalityTolerance',1e-16);
%------------------------------
% NonLinear Optimization
%------------------------------
output_line = lsqnonlin(func,[A(1,1), A(1,3), A(2,2), A(2,3), A(1,2)],...
[],[],options);
%------------------------------------------------------------------------
output = Reshape(output_line);
The Dual Absolute Quadric Function:
function cost = DAQ(params)
Aj = [params(1) params(5) params(2) ;
0 params(3) params(4) ;
0 0 1 ];
Ai = [params(1) params(5) params(2) ;
0 params(3) params(4) ;
0 0 1 ];
% W^-1 (IAC Image of the Absolute Conic)
W_inv = Ai * Aj';
%----------------
%Find plane at infinity from MQM' ~ w (Dual Absolute Quadric)
Plane_at_infinity = PlaneAtInfinity(W_inv);
%Find H_Infty = [e21]F+e21*n'
Homography_at_infty = H_Infty(Plane_at_infinity);
%----------------
% Initialization
%----------------
global Fs;
% Initialize the cost as a vector
% (N-1 * N-2)/2: 9*8/2 = 36
vector_size = (size(Fs,3)-1)*(size(Fs,4)-2)/2;
cost = zeros(1, vector_size);
% Cost Function
k = 0;
loop_size = 3 * vector_size;
Second_Term = W_inv / norm(W_inv,'fro');
for i=1:3:loop_size
k = k+1;
First_Term = Homography_at_infty(:,i:i+2) * W_inv * ((Homography_at_infty(:,i:i+2))');
First_Term = First_Term / norm(First_Term, 'fro');
cost(k) = norm(First_Term - Second_Term,'fro');
end
end
Plane at infinity function:
function P_infty = PlaneAtInfinity(W_inv)
global PPM;
% Symbolic variables
X = sym('X', 'real');
Y = sym('Y', 'real');
Z = sym('Z', 'real');
L2 = sym('L2','real');
n = [X; Y; Z];
% DAQ
Q = [W_inv , (W_inv * n) ;
(n' * W_inv) , (n' * W_inv * n)];
% Get one only camera matrix (any)
M = PPM(:, :, 3);
% Autocalibration equation
m = M * Q * M';
% solve linear equations
solution = solve(m(1, 1) == (L2 * W_inv(1, 1)), ...
m(2, 2) == (L2 * W_inv(2, 2)), ...
m(3, 3) == (L2 * W_inv(3, 3)), ...
m(1, 3) == (L2 * W_inv(1, 3)));
P_infty = [double(solution.X(1)) double(solution.Y(1))...
double(solution.Z(1))]';
Homography at infinity function:
function H_Inf = H_Infty(planeInf)
global Fs;
k = 1;
% (3 x 3) x ((N-1)*(N-2) /2)
H_Inf = zeros(3,3*(size(Fs,3)-1)*(size(Fs,4)-2)/2);%(3*3)*36
for i = 2:size(Fs,3)
for j = i+1:size(Fs,4)
[~, ~, V] = svd(Fs(:,:,i,j)');
epip = V(:,end);
H_Inf(:,k:k+2) = epipole(Fs(:,:,i,j)) * Fs(:,:,i,j)+ epip * planeInf';
k = k+3;
end
end
end
Reshape function:
function output = Reshape(input)
%---------------------
% Reshape Intrinsics
%---------------------
% K = [a skew u0 ;
% 0 B v0 ;
% 0 0 1 ];
output = [input(1) input(5) input(2) ;
0 input(3) input(4) ;
0 0 1 ];
end
Epipole Function:
function epip = epipole(Fs)
% SVD Decompostition of (Fs)^T
[~,~,V] = svd(Fs');
% Get the epipole from the last vector of the SVD
epi = V(:,end);
% Reshape the Vector into Matrix
epip = [ 0 -epi(3) epi(2);
epi(3) 0 -epi(1);
-epi(2) epi(1) 0 ];
end
The plane at infinity has to be calculated as following:
function plane = computePlaneAtInfinity(P, K)
%Input
% P - Projection matrices
% K - Approximate Values of Intrinsics
%
%Output
% plane - coordinate of plane at infinity
% Compute the DIAC W^-1
W_invert = K * K';
% Construct Symbolic Variables to Solve for Plane at Infinity
% X,Y,Z is the coordinate of plane at infinity
% XX is the scale
X = sym('X', 'real');
Y = sym('Y', 'real');
Z = sym('Z', 'real');
XX = sym('XX', 'real');
% Define Normal to Plane at Infinity
N = [X; Y; Z];
% Equation of Dual Absolute Quadric (DAQ)
Q = [W_invert, (W_invert * N); (N' * W_invert), (N' * W_invert * N)];
% Select Any One Projection Matrix
M = P(:, :, 2);
% Left hand side of the equation
LHS = M * Q * M';
% Solve for [X, Y, Z] considering the System of Linear Equations
% We need 4 equations for 4 variables X,Y,Z,XX
S = solve(LHS(1, 1) == (XX * W_invert(1, 1)), ...
LHS(1, 2) == (XX * W_invert(1, 2)), ...
LHS(1, 3) == (XX * W_invert(1, 3)), ...
LHS(2, 2) == (XX * W_invert(2, 2)));
plane = [double(S.X(1)); double(S.Y(1)); double(S.Z(1))];
end
Hi every one >> hope you all are doing fine
I wanted to ask you about calculating the phase values for an image ,, you see I used the Gabor wavlet like so :
k = ( Kmax / ( f ^ v ) ) * exp( 1i * u * pi / 8 );% Wave Vector
kn2 = ( abs( k ) ) ^ 2;
GW = zeros ( R , C );
for m = -R/2 + 1 : R/2
for n = -C/2 + 1 : C/2
GW(m+R/2,n+C/2) = ( kn2 / Delt2 ) * exp( -0.5 * kn2 * ( m ^ 2 + n ^ 2 ) / Delt2) * ( exp( 1i * ( real( k ) * m + imag ( k ) * n ) ) - exp ( -0.5 * Delt2 ) );
end
end
I=imread('a.pgm');
Myimage=conv2(I,double(GW),'same');
then I called the image and the filter with different orientations and scales and stored the phase in P then I wanted to quantize it with rang 4 i:
close all;
clear all;
clc;
% Parameter Setting
R = 32;
C = 32;
Kmax = pi;
f = sqrt( 2 );
Delt = 2 * pi;
Delt2 = Delt * Delt;
% Show the Gabor Wavelets
for v=1:7 %v = 1 : 7
for u = 1:5 % u= 1: 5
[GW,Myimage]= GaborWavelet ( R, C, Kmax, f, u, v, Delt2 ); % Create the Gabor wavelets
figure;
subplot( 5, 8, v * 7 + u ),imshow ( real( GW ) ,[]); % Show the real part of Gabor wavelets
end
figure ;
subplot( 1, 5, v + 1 ),imshow ( abs( GW ),[]); % Show the magnitude of Gabor wavelets
end
%clear I;
R=real(GW);
I=imag(GW);
M=abs(Myimage);
P=atan(imag(Myimage)/real(Myimage)); <<<< is this even right ??
%P=atan(I/R);
save P P;
[xx,yy] = size (P);
DATA =zeros(size(P));
for i=1:48
for j=1:48
for zz=1:3
if (360* zz/4) <= abs(P(i,j))&& abs(P(i,j))<(360*(zz+1)/4)
DATA(i,j)=zz ; end;
end;
end;
end;
save DATA DATA ;
But the data is so small like : -1.49279186693682 1.50990968797986 -1.39225915272978 0.966151874072431
which leads to quantized value of 0 >> Where did I go wrong
I think values seem small because they are given in radians and you expect them in degrees. As for getting the magnitude and angle of a complex number, take a look at http://www.mathworks.fr/fr/help/matlab/ref/angle.html.
I quote:
"For complex Z, the magnitude R and phase angle theta are given by
R = abs(Z)
theta = angle(Z)"
Z would be your GW.
Hope this helps!
i have trouble getting a matlab code to work properly! i found a cubic spline code in matlab to give me the interpolated polynomial. and i simply give it an example to work:
Xi = [0 0.05 0.1]
Fi = [1 1.105171 1.221403]
Fi' = [2 _ 2.442806]
but it gives me this error:
??? Attempted to access du(1); index out of bounds because numel(du)=0.
Error in ==> cubic_nak at 53
du(1) = du(1) - hi(1)^2 / hi(2);
here is the full code for not a knot condition
function csn = cubic_nak ( xi, fi )
%CUBIC_NAK compute the cubic spline interpolant, subject to
% "not-a-knot" boundary conditions, associated with a
% given set of interpolating points and function values
%
% calling sequences:
% csn = cubic_nak ( xi, fi )
% cubic_nak ( xi, fi )
%
% inputs:
% xi vector containing the interpolating points
% (must be sorted in ascending order)
% fi vector containing function values
% the i-th entry in this vector is the function
% value associated with the i-th entry in the 'xi'
% vector
%
% output:
% csn five column matrix containing the information which
% defines the "not-a-knot" cubic spline interpolant
% - first column: interpolating points
% - second column: function values
% - third column: coefficients of linear terms
% - fourth column: coefficients of quadratic terms
% - fifth column: coefficients of cubic terms
%
% NOTE:
% to evaluate the "not-a-knot" cubic spline interpolant apply
% the routine SPLINE_EVAL to the output of this routine
%
n = length ( xi );
m = length ( fi );
if ( n ~= m )
disp ( 'number of ordinates and number of function values must be equal' )
return
end
for i = 1 : n-1
hi(i) = xi(i+1) - xi(i);
end
for i = 1 : n-2
dd(i) = 2.0 * ( hi(i) + hi(i+1) );
ri(i) = (3.0/hi(i+1))*(fi(i+2)-fi(i+1))-(3.0/hi(i))*(fi(i+1)-fi(i));
end
dd(1) = dd(1) + hi(1) + hi(1)^2 / hi(2);
dd(n-2) = dd(n-2) + hi(n-1) + hi(n-1)^2 / hi(n-2);
du = hi(2:n-2);
dl = du;
du(1) = du(1) - hi(1)^2 / hi(2);
dl(n-3) = dl(n-3) - hi(n-1)^2 / hi(n-2);
temp = tridiagonal ( dl, dd, du, ri );
c = zeros ( n,1 );
d = c; b = c;
c(2:n-1) = temp;
c(1) = ( 1 + hi(1) / hi(2) ) * c(2) - hi(1) / hi(2) * c(3);
c(n) = ( 1 + hi(n-1) / hi(n-2) ) * c(n-1) - hi(n-1) / hi(n-2) * c(n-2);
for i = 1 : n-1
d(i) = (c(i+1)-c(i))/(3.0*hi(i));
b(i) = (fi(i+1)-fi(i))/hi(i) - hi(i)*(c(i+1)+2.0*c(i))/3.0;
end
if ( nargout == 0 )
disp ( [ xi' fi' b c d ] )
else
csn = [ xi' fi' b c d ];
end
also for the clamped condition it gives me this error:
??? Undefined function or method 'tridiagonal' for input arguments of type 'double'.
Error in ==> cubic_clamped at 55
c = tridiagonal ( hi(1:n-1), dd, hi(1:n-1), ri );
??? Input argument "xi" is undefined.
Error in ==> cubic_clamped at 35
n = length ( xi );
the full code for clamped mode:
function csc = cubic_clamped ( xi, fi, fpa, fpb )
%CUBIC_CLAMPED compute the cubic spline interpolant, subject to
% "clamped" boundary conditions, associated with a
% given set of interpolating points and function values
%
% calling sequences:
% csc = cubic_clamped ( xi, fi, fpa, fpb )
% cubic_clamped ( xi, fi, fpa, fpb )
%
% inputs:
% xi vector containing the interpolating points
% (must be sorted in ascending order)
% fi vector containing function values
% the i-th entry in this vector is the function
% value associated with the i-th entry in the 'xi'
% vector
% fpa derivative value at left endpoint; i.e., xi(1)
% fpb derivative value at right endpoint; i.e., xi(n)
%
% output:
% csn five column matrix containing the information which
% defines the "clamped" cubic spline interpolant
% - first column: interpolating points
% - second column: function values
% - third column: coefficients of linear terms
% - fourth column: coefficients of quadratic terms
% - fifth column: coefficients of cubic terms
%
% NOTE:
% to evaluate the "clamped" cubic spline interpolant apply
% the routine SPLINE_EVAL to the output of this routine
%
n = length ( xi );
m = length ( fi );
if ( n ~= m )
disp ( 'number of ordinates and number of function values must be equal' )
return
end
for i = 1 : n-1
hi(i) = xi(i+1) - xi(i);
end
dd(1) = 2.0*hi(1); dd(n) = 2.0*hi(n-1);
ri(1) = (3.0/hi(1))*(fi(2)-fi(1)) - 3.0 * fpa;
ri(n) = 3.0 * fpb - (3.0/hi(n-1))*(fi(n)-fi(n-1));
for i = 1 : n-2
dd(i+1) = 2.0 * ( hi(i) + hi(i+1) );
ri(i+1) = (3.0/hi(i+1))*(fi(i+2)-fi(i+1))-(3.0/hi(i))*(fi(i+1)-fi(i));
end
disp ( [dd' ri'] )
c = tridiagonal ( hi(1:n-1), dd, hi(1:n-1), ri );
d = zeros ( n,1 );
b = d;
for i = 1 : n-1
d(i) = (c(i+1)-c(i))/(3.0*hi(i));
b(i) = (fi(i+1)-fi(i))/hi(i) - hi(i)*(c(i+1)+2.0*c(i))/3.0;
end
if ( nargout == 0 )
disp ( [ xi' fi' b c' d ] )
else
csc = [ xi' fi' b c' d ];
end
for this one it only gives me the first 2 columns!
so anyone knows how i can make these 2 work?
Your data only has 3 points. You need 4 (or more) points to fit a cubic, so your out-of-bounds error probably comes from the code looking for another point in the array.