How to calculate Gradient in matlab? - matlab

I am working on pedestrian step detection (acceleration). I want to calculate statistical features from my filtered signal. I have already calculated some and now I want to calculate gradient.
My data is of 1x37205 double. I calculated features using for loop with moving window size=2samples and 50% overlap of previous window. Below I am attaching the code I tried to calculate the gradient.
I am not sure if it is the right way to calculate or not? In addition, I am also unable to understand that what is the purpose to use gradient, how it can be useful for step detection and how to work with gradient? Could some one guide me or provide any code help in matlab?
%%Here M is mean and V is variance i already calculated from filtered data
G = zeros(length(window:length(M)), 2);
for i = window:length(M)
temp = gradient(M(i+1-window:i),V(i+1-window:i));
G(i, 1) = temp(2, 1); % "c1"
G(i, 2) = temp(2, 1); % "c2"
end

One of the best features of Matlab is its documentation. If you are unfamiliar on how to get specific function documentation, enter the following in the command line:
doc functionName
Alternatively, for 'brief' documentation that displays in the command line, you can enter:
help functionName
Also see the documentation link here.
Your question is worded poorly, so I will summarize what I understand and answer accordingly:
You have a step detection data (1*37205) double, let us call it stepSignal
stepSignal is position data
You want your window to be 2 steps with 50% overlap. This is the default behavior for the gradient function.
You do not need a "for" loop to achieve your goal. According to the documentation, "gradient" can take one input.
See the code below, and if need be add clarifications to the original question.
%% Assume that stepSignal is already imported into the workspace
velocity = gradient(stepSignal);
One last note, when you give "gradient" two inputs, it automatically assumes the second input is a uniform spacing value.

Related

Generating Radio propagation pattern in matlab?

I want to implement a part of article. The following explanations are expressed in it.
"we evaluate the performance of proposed localization method at varying degree of irregularity, where DOI defines the radio propagation irregularity per unit degree change in direction. The radio propagation irregularity model used in this paper is shown as follows:"
I have tried to write the code of this part but It doesn't work and can't get a result.
function Coeff=k(i)
Rand=rand(1,100);
DOI=0.02;
if(i==0)
Coeff=1; %Terminating condition
else
while i<360
Coeff=k(i-1)+Rand*DOI; %DOI=[0.01,0.02,0.03,0.04,0.05]
end
end
end
And The following figure has been shown in that article for DOI=0.02...I need to get an output like this, How can I do it
Thanks in advance.
It would help if you post a link to the article, but in this case they just generate a circular path with some noise.
DOI=0.05;
phi = linspace(0,2*pi,360); %360 angles
r=-DOI+2*DOI*rand([1,360]); %random values between -DOI and DOI
r=cumsum(r)+1; %add them to make a path, with mean value 1
while abs(r(end)-r(1))> DOI %start and finish must not be too far away from eachother
r=-DOI+2*DOI*rand([1,360]);
r=cumsum(r)+1;
end
plot(r.*cos(phi),r.*sin(phi),'r',cos(phi),sin(phi),'--b')
axis equal

Interactive curve fitting with MATLAB using custom GUI?

I find examples the best way to demonstrate my question. I generate some data, add some random noise, and fit it to get back my chosen "generator" value...
x = linspace(0.01,1,50);
value = 3.82;
y = exp(-value.*x);
y = awgn(y,30);
options = optimset('MaxFunEvals',1000,'MaxIter',1000,'TolFun',1e-10,'Display','off');
model = #(p,x) exp(-p(1).*x);
startingVals = [5];
lb = [1];
ub = [10];
[fittedValue] = lsqcurvefit(model,startingVals,x,y,lb,ub,options)
fittedGraph = exp(-fittedValue.*x);
plot(x,y,'o');
hold on
plot(x,fittedGraph,'r-');
In this new example, I have generated the same data but this time added much more noise to the first 15 points. Because it is random sometimes it works out okay, but after a few runs I get a good example that illustrates my problem. Same code, except for these lines added under value = 3.82
y = exp(-value.*x);
y(1:15) = awgn(y(1:15),5);
y(15:end) = awgn(y(15:end),30);
As you can see, it has clearly not given a good fit to where the data seems reliable, because it is fitting from points 1-50. What I want to do is say, okay MATLAB, I can see we have some noisy data but it seems decent over a range, only fit your exponential from points 15 to the end. I could go back to my code and update it to do this, but I will be batch fitting graphs like this where each one will have different ranges of 'good' data.
So what I am after is a GUI callback mechanisms that allows me to click on two circles from the data and have them change color or something, which indicates the lsqcurvefit will only fit over that range. Internally all it has to change is inside the lsqcurvefit call e.g.
x(16:end),y(16:end)
But the range should update depending on the starting and ending circles I have clicked.
I hope my question is clear. Thanks.
You could use ginput to select the two points for your min and max in the plot.
[x,y]=ginput(2);
%this returns you the x and y coordinates of two points clicked after each other
%the min point is assumed to be clicked first
min=[x(1) y(1)];
max=[x(2) y(2)];
then you could fit your curve with the coordinates for min and max I guess.
You could also switch between a rightclick for the min and a leftclick for the max etc.
Hope this helps you.

GUI solving equations project

I have a Matlab project in which I need to make a GUI that receives two mathematical functions from the user. I then need to find their intersection point, and then plot the two functions.
So, I have several questions:
Do you know of any algorithm I can use to find the intersection point? Of course I prefer one to which I can already find a Matlab code for in the internet. Also, I prefer it wouldn't be the Newton-Raphson method.
I should point out I'm not allowed to use built in Matlab functions.
I'm having trouble plotting the functions. What I basically did is this:
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
cla % To clear axes when plotting new functions
ezplot(fun_f);
hold on
ezplot(fun_g);
axis ([-20 20 -10 10]);
The problem is that sometimes, the axes limits do not allow me to see the other function. This will happen, if, for example, I will have one function as log10(x) and the other as y=1, the y=1 will not be shown.
I have already tried using all the axis commands but to no avail. If I set the limits myself, the functions only exist in certain limits. I have no idea why.
3 . How do I display numbers in a static text? Or better yet, string with numbers?
I want to display something like x0 = [root1]; x1 = [root2]. The only solution I found was turning the roots I found into strings but I prefer not to.
As for the equation solver, this is the code I have so far. I know it is very amateurish but it seemed like the most "intuitive" way. Also keep in mind it is very very not finished (for example, it will show me only two solutions, I'm not so sure how to display multiple roots in one static text as they are strings, hence question #3).
function [Sol] = SolveEquation(handles)
fun_f = get(handles.Function_f,'string');
fun_g = get(handles.Function_g,'string');
f = inline(fun_f);
g = inline(fun_g);
i = 1;
Sol = 0;
for x = -10:0.1:10;
if (g(x) - f(x)) >= 0 && (g(x) - f(x)) < 0.01
Sol(i) = x;
i = i + 1;
end
end
solution1 = num2str(Sol(1));
solution2 = num2str(Sol(2));
set(handles.roots1,'string',solution1);
set(handles.roots2,'string',solution2);
The if condition is because the subtraction will never give me an absolute zero, and this seems to somewhat solve it, though it's really not perfect, sometimes it will give me more than two very similar solutions (e.g 1.9 and 2).
The range of x is arbitrary, chosen by me.
I know this is a long question, so I really appreciate your patience.
Thank you very much in advance!
Question 1
I think this is a more robust method for finding the roots given data at discrete points. Looking for when the difference between the functions changes sign, which corresponds to them crossing over.
S=sign(g(x)-f(x));
h=find(diff(S)~=0)
Sol=x(h);
If you can evaluate the function wherever you want there are more methods you can use, but it depends on the size of the domain and the accuracy you want as to what is best. For example, if you don't need a great deal of accurac, your f and g functions are simple to calculate, and you can't or don't want to use derivatives, you can get a more accurate root using the same idea as the first code snippet, but do it iteratively:
G=inline('sin(x)');
F=inline('1');
g=vectorize(G);
f=vectorize(F);
tol=1e-9;
tic()
x = -2*pi:.001:pi;
S=sign(g(x)-f(x));
h=find(diff(S)~=0); % Find where two lines cross over
Sol=zeros(size(h));
Err=zeros(size(h));
if ~isempty(h) % There are some cross-over points
for i=1:length(h) % For each point, improve the approximation
xN=x(h(i):h(i)+1);
err=1;
while(abs(err)>tol) % Iteratively improve aproximation
S=sign(g(xN)-f(xN));
hF=find(diff(S)~=0);
xN=xN(hF:hF+1);
[~,I]=min(abs(f(xN)-g(xN)));
xG=xN(I);
err=f(xG)-g(xG);
xN=linspace(xN(1),xN(2),15);
end
Sol(i)=xG;
Err(i)=f(xG)-g(xG);
end
else % No crossover points - lines could meet at tangents
[h,I]=findpeaks(-abs(g(x)-f(x)));
Sol=x(I(abs(f(x(I))-g(x(I)))<1e-5));
Err=f(Sol)-g(Sol)
end
% We also have to check each endpoint
if abs(f(x(end))-g(x(end)))<tol && abs(Sol(end)-x(end))>1e-12
Sol=[Sol x(end)];
Err=[Err g(x(end))-f(x(end))];
end
if abs(f(x(1))-g(x(1)))<tol && abs(Sol(1)-x(1))>1e-12
Sol=[x(1) Sol];
Err=[g(x(1))-f(x(1)) Err];
end
toc()
Sol
Err
This will "zoom" in to the region around each suspected root, and iteratively improve the accuracy. You can tweak the parameters to see whether they give better behaviour (the tolerance tol, the 15, number of new points to generate, could be higher probably).
Question 2
You would probably be best off avoiding ezplot, and using plot, which gives you greater control. You can vectorise inline functions so that you can evaluate them like anonymous functions, as I did in the previous code snippet, using
f=inline('x^2')
F=vectorize(f)
F(1:5)
and this should make plotting much easier:
plot(x,f(x),'b',Sol,f(Sol),'ro',x,g(x),'k',Sol,G(Sol),'ro')
Question 3
I'm not sure why you don't want to display your roots as strings, what's wrong with this:
text(xPos,yPos,['x0=' num2str(Sol(1))]);

least mean square filter to reduce noise in image?

I have a reference image and output image which is having lot of noise.I created a mask for a portion in both images.I wanna design a filter which when applied to this region,can be applied to whole region.i am using least mean square method to reduce noise.But each time the mean square keeps increasing.Any idea how to sort out this problem.I am using MAT LAB to do this.Here is my code.
output=double(imread('obtained_output.jpg'));
reference=double(imread('reference_output.jpg'));
[M,N]=size(output);
upper_mask_obtained = output(1:100, 1:100);
lower_mask_obtained=output(201:300,1:100);
total_mask_obtained=[upper_mask_obtained;lower_mask_obtained];
upper_mask_reference = reference(1:100, 1:100);
lower_mask_reference=reference(201:300,1:100);
total_mask_reference=[upper_mask_reference;lower_mask_reference];
Ns=5;
[a,b]=size(total_mask_reference);
u=.000000001;
W=ones(Ns,Ns);
Y=zeros(Ns,Ns);
DD=zeros(Ns,Ns);
error=zeros(M,N);
e=zeros(Ns,Ns);
error_mask=abs(total_mask_obtained-total_mask_reference);
s= sum(sum(error_mask.^2));
mean_square_error=(s/(a*b));
while(mean_square_error>7)
for m=1+Ns:200
for n=1+Ns:100
for l=1:Ns
for k=1:Ns
Y(l,k)=total_mask_obtained(m-Ns+l-1,n-Ns+k-1);
DD(l,k)=total_mask_reference(m-Ns+l-1,n-Ns+k-1);
end
end
Z=conv2(Y,W,'same')/sum(sum(W));
e=DD(3,3)-Z(3,3);
W=(W+u*e*Y);
total_mask_obtained(m-Ns+2,n-Ns+2)=Z(3,3);
end
end
error=total_mask_reference-total_mask_obtained;
mean_square_error=sum(sum(error.^2))/(a*b);
end
figure(2);
final_output=(conv2(output,W,'same')/(sum(sum(W))));
imshow(uint8(final_output));
I think your task could be well-accomplished by using Gaussian filter. It is already built-in in Matlab. http://www.mathworks.com/help/images/ref/fspecial.html Check this for your reference. Sorry I'm new in StackOverflow. So I can't add comments yet. Sorry if it is not answer to your question.

Detect signal jumps relative to local activity

In Matlab, is it possible to measure local variation of a signal across an entire signal without using for loops? I.e., can I implement the following:
window_length = <something>
for n = 1:(length_of_signal - window_length/2)
global_variance(n) = var(my_signal(1:window_length))
end
in a vectorized format?
If you have the image processing toolbox, you can use STDFILT:
global_std = stdfilt(my_signal(:),ones(window_length,1));
% square to get the variance
global_variance = global_std.^2;
You could create a 2D array where each row is shifted one w.r.t. to the row above, and with the number of rows equal to the window width; then computing the variance is trivial. This doesn't require any toolboxes. Not sure if it's much faster than the for loop though:
longSignal = repmat(mySignal(:), [1 window_length+1]);
longSignal = reshape(longSignal(1:((length_of_signal+1)*window_length)), [length_of_signal+1, window_length])';
global_variance = sum(longSignal.*longSignal, 2);
global_variance = global_variance(1:length_of_signal-window_length));
Note that the second column is shifted down by one relative to the one above - this means that when we have the blocks of data on which we want to operate in rows, so I take the transpose. After that, the sum operator will sum over the first dimension, which gives you a row vector with the results you want. However, there is a bit of wrapping of data going on, so we have to limit to the number of "good" values.
I don't have matlab handy right now (I'm at home), so I was unable to test the above - but I think the general idea should work. It's vectorized - I can't guarantee it's fast...
Check the "moving window standard deviation" function at Matlab Central. Your code would be:
movingstd(my_signal, window_length, 'forward').^2
There's also moving variance code, but it seems to be broken.
The idea is to use filter function.