So I'm pretty new to MATLAB and numerical analysis and I'm trying to write the code for the secant method, but for some reason it just stops after the first iteration.
Here is my code for the secant method:
function [root] = secant(func, x0, x1, N, eps_step, max_eps)
last_x = x0;
curr_x = x1;
new_x = x1;
diff_x = curr_x - last_x;
diff_f = func(curr_x) - func(last_x);
k = 0;
if func(x0) == 0
root = x0;
fprintf('results for secant iterations \n');
fprintf(' x0,x1 k x_k f(x_k) |x_k-x_(k+1)|\n')
fprintf(' --------------- --- ----------- --------- ---------------\n')
fprintf('N = %12.8f {x0=%12.8f,x1=%12.8f} %3i %12.8f %12.8f %12.8f \neps = %3i \ndelta = %3i \n\n',N, last_x, curr_x, k ,last_x,func(new_x), diff_x, eps_step, max_eps)
return;
elseif func(x1) == 0
root = x1;
fprintf('results for secant iterations \n');
fprintf(' x0,x1 k x_k f(x_k) |x_k-x_(k+1)|\n')
fprintf(' --------------- --- ----------- --------- ---------------\n')
fprintf('N = %12.8f {x0=%12.8f,x1=%12.8f} %3i %12.8f %12.8f %12.8f \neps = %3i \ndelta = %3i \n\n',N, last_x, curr_x, k ,curr_x,func(new_x), diff_x, eps_step, max_eps)
return;
end
while (k < N)
k = k+1;
diff_x = curr_x - last_x;
diff_f = func(curr_x) - func(last_x);
new_x = curr_x - func(curr_x)*(diff_x/diff_f); % compute the new value of x
% if abs((new_x - curr_x)*(diff_f/diff_x)+func(curr_x)) < max_eps
fprintf('eps_step = %12.8f\n', eps_step); %Doesnt print this line for some reason
if (abs(diff_x) < eps_step)
if (abs(diff_f) < max_eps && new_x > 0)
root = new_x;
fprintf('results for secant iterations \n');
fprintf(' x0,x1 k x_k f(x_k) |x_k-x_(k+1)|\n')
fprintf(' --------------- --- ----------- --------- ---------------\n')
fprintf('N = %12.8f {x0=%12.8f,x1=%12.8f} %3i %12.8f %12.8f %12.8f \neps = %3i \ndelta = %3i \n\n',N, x0, x1, k ,new_x,func(new_x), diff_x, eps_step, max_eps)
break
end
end
last_x = curr_x;
curr_x = new_x;
end
end
the function and call function are:
func = #(x) x.^2-0.2-4*x.*sin(x)+(2*sin(x)).^2;
secant(func, 0, 1, 50, 10^-6, 10^-6);
But the result I get is:
results for secant iterations
x0,x1 k x_k f(x_k) |x_k-x_(k+1)|
--------------- --- ----------- --------- ---------------
N = 50.00000000 {x0= 0.00000000,x1= 1.00000000} 1 0.42880752 -0.03777984 1.00000000
eps = 1.000000e-06
delta = 1.000000e-06
the root is supposed to be 0.484736. Where is the mistake?
Related
Consider the following calculation of the tangent tangent correlation which is performed in a for loop
v1=rand(25,1);
v2=rand(25,1);
n=25;
nSteps=10;
mean_theta = zeros(nSteps,1);
for j=1:nSteps
theta=[];
for i=1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta = [theta acosd(d/n1/n2)];
end
mean_theta(j)=mean(theta);
end
plot(mean_theta)
How can matlab matrix calculations be utilized to make this performance better?
There are several things you can do to speed up your code. First, always preallocate. This converts:
theta = [];
for i = 1:(n-j)
%...
theta = [theta acosd(d/n1/n2)];
end
into:
theta = zeros(1,n-j);
for i = 1:(n-j)
%...
theta(i) = acosd(d/n1/n2);
end
Next, move the normalization out of the loops. There is no need to normalize over and over again, just normalize the input:
v = [v1,v2];
v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
%...
theta(i) = acosd(dot(v(i,:),v(i+j,:)));
This does change the output very slightly, within numerical precision, because the different order of operations leads to different floating-point rounding error.
Finally, you can remove the inner loop by vectorizing that computation:
i = 1:(n-j);
theta = acosd(dot(v(i,:),v(i+j,:),2));
Timings (n=25):
Original: 0.0019 s
Preallocate: 0.0013 s
Normalize once: 0.0011 s
Vectorize: 1.4176e-04 s
Timings (n=250):
Original: 0.0185 s
Preallocate: 0.0146 s
Normalize once: 0.0118 s
Vectorize: 2.5694e-04 s
Note how the vectorized code is the only one whose timing doesn't grow linearly with n.
Timing code:
function so
n = 25;
v1 = rand(n,1);
v2 = rand(n,1);
nSteps = 10;
mean_theta1 = method1(v1,v2,nSteps);
mean_theta2 = method2(v1,v2,nSteps);
fprintf('diff method1 vs method2: %g\n',max(abs(mean_theta1(:)-mean_theta2(:))));
mean_theta3 = method3(v1,v2,nSteps);
fprintf('diff method1 vs method3: %g\n',max(abs(mean_theta1(:)-mean_theta3(:))));
mean_theta4 = method4(v1,v2,nSteps);
fprintf('diff method1 vs method4: %g\n',max(abs(mean_theta1(:)-mean_theta4(:))));
timeit(#()method1(v1,v2,nSteps))
timeit(#()method2(v1,v2,nSteps))
timeit(#()method3(v1,v2,nSteps))
timeit(#()method4(v1,v2,nSteps))
function mean_theta = method1(v1,v2,nSteps)
n = numel(v1);
mean_theta = zeros(nSteps,1);
for j = 1:nSteps
theta=[];
for i=1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta = [theta acosd(d/n1/n2)];
end
mean_theta(j) = mean(theta);
end
function mean_theta = method2(v1,v2,nSteps)
n = numel(v1);
mean_theta = zeros(nSteps,1);
for j = 1:nSteps
theta = zeros(1,n-j);
for i = 1:(n-j)
d = dot([v1(i) v2(i)],[v1(i+j) v2(i+j)]);
n1 = norm([v1(i) v2(i)]);
n2 = norm([v1(i+j) v2(i+j)]);
theta(i) = acosd(d/n1/n2);
end
mean_theta(j) = mean(theta);
end
function mean_theta = method3(v1,v2,nSteps)
v = [v1,v2];
v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
n = numel(v1);
mean_theta = zeros(nSteps,1);
for j = 1:nSteps
theta = zeros(1,n-j);
for i = 1:(n-j)
theta(i) = acosd(dot(v(i,:),v(i+j,:)));
end
mean_theta(j) = mean(theta);
end
function mean_theta = method4(v1,v2,nSteps)
v = [v1,v2];
v = v./sqrt(sum(v.^2,2)); % Can use VECNORM in newest MATLAB
n = numel(v1);
mean_theta = zeros(nSteps,1);
for j = 1:nSteps
i = 1:(n-j);
theta = acosd(dot(v(i,:),v(i+j,:),2));
mean_theta(j) = mean(theta);
end
Here is a full vectorized solution:
i = 1:n-1;
j = (1:nSteps).';
ij= min(i+j,n);
a = cat(3, v1(i).', v2(i).');
b = cat(3, v1(ij), v2(ij));
d = sum(a .* b, 3);
n1 = sum(a .^ 2, 3);
n2 = sum(b .^ 2, 3);
theta = acosd(d./sqrt(n1.*n2));
idx = (1:nSteps).' <= (n-1:-1:1);
mean_theta = sum(theta .* idx ,2) ./ sum(idx,2);
Result of Octave timings for my method,method4 from the answer provided by #CrisLuengo and the original method (n=250):
Full vectorized : 0.000864983 seconds
Method4(Vectorize) : 0.002774 seconds
Original(loop) : 0.340693 seconds
I've attempted to run this code multiple times and have had zero luck since I added in the last for loop. Before the error, the vector k wouldn't update so the vector L was the same number repeated.
I can't figure out why I am getting the 'Not enough input arguments' error when it was working fine beforehand.
Any help would be much appreciated!
% Set up parameters of the functions
omega = 2*pi/10; % 1/s
g = 9.81; % m/s^2
h = 20; % m
parms = [omega, g, h];
% Set up the root finding variables
etol = 1e-6; % convergence criteria
iter = 100; % maximum number of iterations
f = #my_fun; % function pointer to my_func
fp = #my_fprime; % function pointer to my_fprime
k0 = kguess(parms); % initial guess for root
% Find the root
[k, error, n_iterations] = newtraph(f, fp, k0, etol, iter, parms);
% Get the wavelength
if n_iterations < iter
% Converged correctly
L = 2 * pi / k;
else
% Did not converge
disp('ERROR: Maximum number of iterations exceeded')
return
end
wave = load('wavedata.dat');
dt = 0.04; %s
%dh = 0.234; %water depth in meters
wave = wave*.01; %covnverts from meters to cm
nw = wave([926:25501],1);
a = length(nw);
t = 0;
spot = 1;
points = zeros(1,100);
for i = 1:a-1
t=t+dt;
if nw(i) < 0
if nw(i+1) > 0
points(spot)=t;
spot=spot+1;
t=0;
end
end
end
omega = 2*pi./points; %w
l = length(points);
L = zeros(1,509);
k = zeros(1,509);
for j = 1:l
g = 9.81; % m/s^2
h = 0.234; % m
parms = [omega(j), g, h];
% Set up the root finding variables
etol = 1e-6; % convergence criteria
iter = 100; % maximum number of iterations
f = #my_fun; % function pointer to my_func
fp = #my_fprime; % function pointer to my_fprime
k0(j) = kguess(parms); % initial guess for root
% Find the root
[k(j), error, n_iterations] = newtraph(f, fp, k0(j), etol, iter, parms);
% Get the wavelength
if n_iterations < iter
% Converged correctly
L(j) = 2 * pi / k(j);
else
% Did not converge
disp('ERROR: Maximum number of iterations exceeded')
return
end
end
function [ f ] = my_fun(k,parms)
%MY_FUN creates a function handle for linear dispersion
% Detailed explanation goes here
w = parms(1) ;
g = parms(2);
h = parms(3);
f = g*k*tanh(k*h)-(w^2);
end
function [ fp ] = my_fprime(k,parms)
%MY_FPRIME creates a function handle for first derivative of linear
% dispersion.
g = parms(2);
h = parms(3);
% w = 2*pi/10; % 1/s
% g = 9.81; % m/s^2
% h = 20; % m
fp = g*(k*h*((sech(k*h)).^2) + tanh(k*h));
end
function [ k, error, n_iterations ] = newtraph( f, fp, k0, etol, iterA, parms )
%NEWTRAPH Estimates the value of k using the newton raphson method.
if nargin<3,error('at least 3 input arguments required'),end
if nargin<4|isempty(etol),es=etol;end
if nargin<5|isempty(iterA),maxit=iterA;end
iter = 0;
k = k0;
%func =#f;
%dfunc =#fp;
while (1)
xrold = k;
k = k - f(k)/fp(k);
iter = iter + 1;
if k ~= 0, ea = abs((k - xrold)/k) * 100; end
if ea <= etol | iter >= iterA, break, end
end
error = ea;
n_iterations = iter;
end
In function newtraph at line 106 (second line in the while(1) loop), you forgot to pass parms to the function call f:
k = k - f(k)/fp(k);
should become
k = k - f(k,parms)/fp(k,parms);
I'm trying to reduce the processing time of bilinear interpolation of an image on a set of points. First I did a normal for loop. I can't use parfor since I'm already using it on the function that is calling the interp. I tried to vectorize the function, it works, but there is almost no reduce in processing time.
Any ideas of how can I improve the vectorized version?
Some results:
Edited - The results were varying a lot before. I don't know why, but now they seam consistent and the values don't change much.
I added the tmirt2D as #Dev-iL pointed it out. His code is a a lot faster (~3x) than mine, and he uses C++.
Interp 2D tester
Time for each point and speed up in '%' based on the reference time.
Array size: 10000. Repeat: 10. Loops: 20
Normal for loop interp: 145.6354 ns (reference time)
Vect interp (in bounds): 68.6679 ns (112.09%)
Vect interp (out boudns): 66.5793 ns (118.74%)
Vect interp nearest (in boudns): 28.2870 ns (414.85%)
Vect interp nearest (out boudns): 26.3854 ns (451.95%)
tmirt2D from File Exchange: 22.6089 ns (544.15%)
Matlab interp2 linear: 921.0408 ns (-84.19%)
Matlab interp2 nearest: 911.7492 ns (-84.03%)
Testing code:
clearvars; clc; close all;
mustCompareMatlab = 1;
tm1 = 0;
tm2 = 0;
tm3 = 0;
tm4 = 0;
tm5 = 0;
tm6 = 0;
tm7 = 0;
tmirt2D = 0;
baseLoopN = 10;
for j=1:baseLoopN
%% Create data
dataSize = [1200 1600];
data = rand(dataSize)*255;
N = 1e4;
X = rand(1,N)*dataSize(2);
Y = rand(1,N)*dataSize(1);
% Only inside bounds-1 coordinates
Xin = X(X<dataSize(2)-1);
Yin = Y(Y<dataSize(1)-1);
% make X and Y same size
Xin(end+1:length(X)) = ones(1,length(X)-length(Xin));
Yin(end+1:length(X)) = ones(1,length(X)-length(Yin));
% Make sure X and Y have outside bounds values
X(1) = dataSize(2) + 1;
Y(1) = dataSize(1) + 1;
loops = 20;
% Catch
interpData = Interp2D(data,X,Y);
tic
for i=1:loops
interpData = Interp2D(data,X,Y);
end
tm1 = tm1 + toc;
%% Only inside bounds coordinates
% Catch
interpData = Interp2DVect(data,Xin,Yin);
tic
for i=1:loops
interpData = Interp2DVect(data,Xin,Yin);
end
tm2 = tm2 + toc;
%% inside and outside bounds
% Catch
interpData = Interp2DVect(data,X,Y);
tic
for i=1:loops
interpDataInterp2DVect = Interp2DVect(data,X,Y);
end
tm3 = tm3 + toc;
%% inside bounds nearest
% Catch
interpData = Interp2DNearest(data,Xin,Yin);
tic
for i=1:loops
interpData = Interp2DNearest(data,Xin,Yin);
end
tm4 = tm4 + toc;
%% inside and outside bounds nearest
% Catch
interpData = Interp2DNearest(data,X,Y);
tic
for i=1:loops
interpData = Interp2DNearest(data,X,Y);
end
tm5 = tm5 + toc;
% mirt2D_mexinterp
% www.mathworks.com/matlabcentral/fileexchange/24183-2d-interpolation
interpData = mirt2D_mexinterp(data,X,Y);
tic
for i=1:loops
interpDataMirt2D = mirt2D_mexinterp(data,X,Y);
end
tmirt2D = tmirt2D + toc;
%% Matlab interp
if mustCompareMatlab
interpData = interp2(data,X,Y,'linear'); %#ok<*NASGU>
tic
for i=1:loops
interpData = interp2(data,Xin,Yin,'linear');
end
tm6 = tm6 + toc;
interpData = interp2(data,X,Y,'nearest');
tic
for i=1:loops
interpData = interp2(data,Xin,Yin,'nearest');
end
tm7 = tm7 + toc;
end
%%
end
A = interpDataInterp2DVect;
B = interpDataMirt2D;
C = A-B;
fprintf('Interp 2D tester\n');
fprintf('Array size: %d. Repeat: %d. Loops: %d\n',N,baseLoopN,loops);
tm1 = tm1*1e9/(baseLoopN*loops*N);
fprintf('Normal for loop interp: %.4f ns\n',tm1);
tm2 = tm2*1e9/(baseLoopN*loops*N);
fprintf('Vect interp (in bounds): %.4f ns (%.2f%%)\n',tm2,100*(tm1/tm2-1));
tm3 = tm3*1e9/(baseLoopN*loops*N);
fprintf('Vect interp (out boudns): %.4f ns (%.2f%%)\n',tm3,100*(tm1/tm3-1));
tm4 = tm4*1e9/(baseLoopN*loops*N);
fprintf('Vect interp nearest (in boudns): %.4f ns (%.2f%%)\n',tm4,100*(tm1/tm4-1));
tm5 = tm5*1e9/(baseLoopN*loops*N);
fprintf('Vect interp nearest (out boudns): %.4f ns (%.2f%%)\n',tm5,100*(tm1/tm5-1));
tmirt2D = tmirt2D*1e9/(baseLoopN*loops*N);
fprintf('tmirt2D from File Exchange: %.4f ns (%.2f%%)\n',tmirt2D,100*(tm1/tmirt2D-1));
if mustCompareMatlab
tm6 = tm6*1e9/(baseLoopN*loops*N);
fprintf('Matlab interp2 linear: %.4f ns (%.2f%%)\n',tm6,100*(tm1/tm6-1));
tm7 = tm7*1e9/(baseLoopN*loops*N);
fprintf('Matlab interp2 nearest: %.4f ns (%.2f%%)\n',tm7,100*(tm1/tm7-1));
end
Normal version:
function [interpData] = Interp2D(data,X,Y)
[sizY, sizX] = size(data);
interpData =zeros(1,length(X),'like',X);
for item=1:length(X),
valX=floor(X(item));
valY=floor(Y(item));
valYp1=valY+1;
valXp1=valX+1;
if (sizY < valYp1)||(sizX < valXp1)|| valX<=0 || valY<=0
interpData(item)=NaN;
else
Inten00=data(valY,valX);
Inten10=data(valY,valXp1);
Inten01=data(valYp1,valX);
Inten11=data(valYp1,valXp1);
px=(X(item))-valX;
py=(Y(item))-valY;
interpData(item)=((1-px)*Inten00+px*Inten10)*(1-py)+((1-px)*Inten01+px*Inten11)*py;
end
end
Vectorized version:
% Images borders are disconsidered due to simplicity
function [interpData,outBounds] = Interp2DVect(data,X,Y)
[sizeY, sizeX] = size(data);
fX = floor(X);
fY = floor(Y);
sizeOkFlag = ~((sizeY-1 < fY)|(sizeX-1 < fX)| fX <= 0 | fY <= 0);
sizeAllOk = min(sizeOkFlag) >= 1;
outBounds = ~sizeAllOk;
% If we have some invalid points, lets set them to NaN
if ~sizeAllOk
interpData = nan(1,length(X),'like',X);
% Prevent invalid data indexes
fX = fX(sizeOkFlag);
fY = fY(sizeOkFlag);
X = X(sizeOkFlag);
Y = Y(sizeOkFlag);
end
pX = X - fX;
pY = Y - fY;
% We need to get the linear indexes
% www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html
%ids00 = sub2ind(dataSize, fY, fX);
% A fast replacement for sub2ind
% http://tipstrickshowtos.blogspot.com.br/2010/02/fast-replacement-for-sub2ind.html
%idsYX
ids00 = fY + (fX-1).*sizeY;
ids01 = fY + (fX).*sizeY;
ids10 = fY+1 + (fX-1).*sizeY;
ids11 = fY+1 + fX.*sizeY;
if sizeAllOk
interpData = ((1-pX).*data(ids00) + pX.*data(ids01)).*(1-pY) + ...
((1-pX).*data(ids10) + pX.*data(ids11)).*pY;
else
interpData(sizeOkFlag) = ((1-pX).*data(ids00) + pX.*data(ids01)).*(1-pY) + ...
((1-pX).*data(ids10) + pX.*data(ids11)).*pY;
if (size(X,1) > 1)
interpData = interpData';
end
end
Nearest version (just to compare)
function [interpData] = Interp2DNearest(data,X,Y)
[sizeY, sizeX] = size(data);
X = round(X);
Y = round(Y);
sizeOkFlag = ~((sizeY-1 < Y)|(sizeX-1 < X)| X <= 0 | Y <= 0);
% Slower if use this:
%sizeAllOk = min(sizeOkFlag) >= 1;
% if sizeAllOk
% ids = Y + (X-1).*sizeY;
% interpData = data(ids);
% else
interpData = nan(1,length(X),'like',X);
X = X(sizeOkFlag);
Y = Y(sizeOkFlag);
ids = Y + (X-1).*sizeY;
interpData(sizeOkFlag) = data(ids);
Click here to see the figure. When I run and plot X and solution, it seems like the data is not sorted. The previous error regarding subscripted dimension mismatch is gone now. Below is my main code:
clear all
y0 = 20000; % initial conditions
iter = 0;
years = 5;
solution = [];
X = [];
for p = 1:1:years
iter = iter+1;
display(iter)
ll = 273;
ul = 273 + 91;
wl = (ul-ll).*rand(1,1) + ll;
yearlength = wl+0.1;
finaltime = p*yearlength;
t = 0:finaltime;
mugen;
Kgen;
d1gen;
n = 2;
deltat = 1;
tspan = 0:deltat:finaltime;
options = odeset('RelTol',1e-10,'AbsTol',1e-10);
sol = ode23s(#(t,y)para_1d(t,y,n,mug,Kg,d1g),tspan,y0,options);
X = [X sol.x];
Y = (sol.y)';
ny = length(Y);
Ytrans = Y';
solution = [solution Ytrans(1,:)] ;
%display(Ytrans(1,end))
clearvars -except solution solution1 iter X
y0 = solution(end,end);
display(y0)
end
plot(x, solution)
This is the function where my ode is:
function dy = para_1d(t, y,n, mug, Kg, d1g)
count = ceil(t)+1;
dy(1,1) = (mug(count).*(y(1).^n)/(Kg(count).^n+y(1).^n)) - d1g(count).*y(1);
and the parameter files are:
x1 = [0 91.25 91.26 182.5 182.51 273.75 273.76 wl];
clear x
for n = 1:p;
x(n,:) = (n-1)*(wl+0.1) + x1;
end
counter = 0;
for j=1:p
for i=1:8
counter = counter+1;
xnew(counter) = x(j,i);
end
end
y1 = [500 500 1500 1500 500 500 0 0];
clear y
for n = 1:p;
y(n,:) = y1;
end
counter = 0;
for j = 1:p
for i = 1:8
counter = counter+1;
ynew(counter) = y(j,i);
end
end
w = y(1,:);
for l = 2:p
w = [w y(l,:)];
end
v = x(1,:);
for q = 2:p
v = [v x(q,:)];
end
mug = pchip(v,w,t);
The parameter K is:
x1 = [0 91.25 91.26 182.5 182.51 273.75 273.76 wl];
clear x
for n = 1:p;
x(n,:) = (n-1)*(wl + 0.1) + x1;
end
counter = 0;
for j = 1:p
for i = 1:8
counter = counter + 1;
xnew(counter) = x(j,i);
end
end
%y1 = [8000 8000 27000 27000 8000 8000 6000 6000 ];
%y1 = [8000 8000 12000 12000 8000 8000 6000 6000 ];
y1 = [6000 6000 8000 8000 6000 6000 6000 6000 ];
clear y
for n = 1:p;
y(n,:) = y1;
end
counter = 0;
for j = 1:p
for i = 1:8
counter = counter+1;
ynew(counter) = y(j,i);
end
end
w = y(1,:);
for l = 2:p
w = [w y(l,:)];
end
v = x(1,:);
for q = 2:p
v = [v x(q,:)];
end
Kg = pchip(v,w,t);
and the last parameter is:
x1 = [0 91.25 91.26 182.5 182.51 273.75 273.76 wl];
clear x
for n=1:p;
x(n,:) = (n-1)*(wl + 0.1) + x1;
end
counter=0;
for j=1:p
for i=1:8
counter=counter+1;
xnew(counter) = x(j,i);
end
end
y1 = [ 0.02272 0.02272 0.04 0.04 0.02272 0.02272 0.005263 0.005263 ];
clear y
for n=1:p;
y(n,:) = y1;
end
counter=0;
for j=1:p
for i=1:8
counter=counter+1;
ynew(counter) = y(j,i);
end
end
w=y(1,:);
for l=2:p
w=[w y(l,:)];
end
v=x(1,:);
for q=2:p
v=[v x(q,:)];
end
d1g = pchip(v,w,t);
You can simply look at the main code and suggest me where I am doing mistake. The parameter codes and ode file is only for those who want to run the code for a clearer view. Thanks a lot for your time!
i have to find the mid points of each lane in a binary iamge , i wrote a code but that is too long and its give error when ever i change the pic of road . i have to save the mid points of each lane and then by finding slope and intercept i have to draw lines on that binary image.
here is the code
x=imread('C:\users\guest\documents\matlab\1.png');
[q,r]= size(x);
n4=zeros(q,r);
midpoint= zeros (720,2); % Array to store midlle points of road lane.
% finding mid points of both lanes.
for n3=540:720
s=x(n3,:);
startIndex =1;
lastIndex =1280;
pixelsRow =s;
FirstWhiteStart=0; FirstWhiteEnd=0; SecondWhiteStart=0; SecondWhiteEnd=0;
for k=1:1280
if (pixelsRow(k) == 1)&&(FirstWhiteStart == 0)
FirstWhiteStart =k;
elseif (pixelsRow(k)==0)&&(FirstWhiteStart>0)&&(FirstWhiteEnd==0)
FirstWhiteEnd=k-1;
elseif (pixelsRow(k)== 1)&&(FirstWhiteEnd>0)&&(SecondWhiteStart==0)
SecondWhiteStart=k;
elseif (pixelsRow(k)==0)&&(SecondWhiteStart>0)&&(SecondWhiteEnd==0)
SecondWhiteEnd=k-1;
end
end
m1=(FirstWhiteStart + FirstWhiteEnd)./2; % first lanes middle point
m1r = round(m1);
if (m1r <= 1)
mp= sub2ind(size(midpoint),n3,1);
midpoint(mp) = 0;
elseif (m1r > 1)
indices = sub2ind(size(n4),n3,m1r);
n4(indices) = 1;
if (m1r >=640)
mp= sub2ind(size(midpoint),n3,2);
midpoint(mp) = m1r;
elseif (m1r <= 640)
mp= sub2ind(size(midpoint),n3,1);
midpoint(mp) = m1r;
end
end
m2=(SecondWhiteStart + SecondWhiteEnd+1)./2; % second lane middle point.
m2r = round(m2);
if (m2r <= 1)
indices = sub2ind(size(n4),n3,m2r);
n4(indices) = 0;
mp= sub2ind(size(midpoint),n3,1);
midpoint(mp) = 0;
elseif (m2r > 1)
indices = sub2ind(size(n4),n3,m2r);
n4(indices) = 1;
if (m2r >=640)
mp= sub2ind(size(midpoint),n3,2);
midpoint(mp) = m2r;
elseif (m2r <=640)
mp= sub2ind(size(midpoint),n3,1);
midpoint(mp) = m2r;
end
end
end
pairpoints = nchoosek([540:720],2);
var1 = zeros (16290,2); % array to store variables a and b of first lane.
var2 = zeros (16290,2); % array to stote variables a and b of second lane.
% calling middle points previously stored in array,putting in equation.
for n = 1 : 16290
x1 = pairpoints(n,1); %value of frst row
x2 = pairpoints(n,2); %value of 2nd row
y1 = midpoint (pairpoints(n,1), 1); %rows of midpoint matrix are specified from pairpoints location martix
y2 = midpoint (pairpoints(n,2), 1);
z1 = midpoint (pairpoints(n,1), 2);
z2 = midpoint (pairpoints(n,2), 2);
a1 = (y2 - y1) ./ (x2 - x1);
a2 = (z2 - z1) ./ (x2 - x1);
b1=(((x2)*(y1)) - (x1)*(y2)) ./ (x2 - x1);
b2=(((x2)*(z1)) - (x1)*(z2)) ./ (x2 - x1);
% variables a and b of first lane.
line = sub2ind(size(var1),n,1);
var1(line) = a1;
line = sub2ind(size(var1),n,2);
var1(line) = b1;
% variables A and b of second lane.
line = sub2ind(size(var2),n,1);
var2(line) = a2;
line = sub2ind(size(var2),n,2);
var2(line) = b2;
end
v11=round(var1);
v22=round(var2);
% eleminating zeros from array.
[i,j] = find(v11);
a1 = v11(i,1);
a1= a1(a1~=0);
b1 = v11(i,2);
b1= b1(b1~=0);
a11=median(a1)
b11=median(b1)
% eleminating zeros from array.
[k,l] = find(v22);
row = i;
a2 = v22(k,1);
a2= a2(a2~=0);
b2 = v22(k,2);
b2= b2(b2~=0);
a22=median(a2)
b22=median(b2)
%assign variables
lin=zeros(720,2);
% implementation of final line equation.
for x1 = 1:720
% equation becomes (w = eh + f) as actual was (y = ax + b)
y1 = (a11 * x1) + b11;
y2 = (a22 * x1) + b22;
col = sub2ind( size(lin),x1,1); % equation for first lane.
lin(col)= y1;
col = sub2ind( size(lin),x1,2); % equation for second lane.
lin(col)= y2;
end
array=lin;
r= 1:720;
c= 1:1280;
x(r,c)= 0;
imshow(x);
imwrite(x,'a.png');
image =imread('C:\users\guest\documents\matlab\a.png');
for r1 = 1:720
for c = 1:2;
if array(r1,c) < 0;
lin(r1,c) = abs (array(r1,c));
image(r1,lin(r1,c))= 0;
elseif array(r1,c) > 0;
image(r1,lin(r1,c))= 1;
end
end
end
imshow(image)