Interpolation using polyfit (Matlab) - matlab

My script is supposed to run Runge-Kutta and then interpolate around the tops using polyfit to calculate the max values of the tops. I seem to get the x-values of the max points correct but the y-values are off for some reason. Have sat with it for 3 days now. The problem should be In the last for-loop when I calculate py?
Function:
function funk = FU(t,u)
L0 = 1;
C = 1*10^-6;
funk = [u(2); 2.*u(1).*u(2).^2./(1+u(1).^2) - u(1).*(1+u(1).^2)./(L0.*C)];
Program:
%Runge kutta
clear all
close all
clc
clf
%Given values
U0 = [240 1200 2400];
L0 = 1;
C = 1*10^-6;
T = 0.003;
h = 0.000001;
W = [];
% Runge-Kutta 4
for i = 1:3
u0 = [0;U0(i)];
u = u0;
U = u;
tt = 0:h:T;
for t=tt(1:end-1)
k1 = FU(t,u);
k2 = FU(t+0.5*h,u+0.5*h*k1);
k3 = FU((t+0.5*h),(u+0.5*h*k2));
k4 = FU((t+h),(u+k3*h));
u = u + (1/6)*(k1+2*k2+2*k3+k4)*h;
U = [U u];
end
W = [W;U];
end
I1 = W(1,:); I2 = W(3,:); I3 = W(5,:);
dI1 = W(2,:); dI2 = W(4,:); dI3 = W(6,:);
I = [I1; I2; I3];
dI = [dI1; dI2; dI3];
%Plot of the currents
figure (1)
plot(tt,I1,'r',tt,I2,'b',tt,I3,'g')
hold on
legend('U0 = 240','U0 = 1200','U0 = 2400')
BB = [];
d = 2;
px = [];
py = [];
format short
for l = 1:3
[H,Index(l)]=max(I(l,:));
Area=[(Index(l)-2:Index(l)+2)*h];
p = polyfit(Area,I(Index(l)-2:Index(l)+2),4);
rotp(1,:) = roots([4*p(1),3*p(2),2*p(3),p(4)]);
B = rotp(1,2);
BB = [BB B];
Imax(l,:)=p(1).*B.^4+p(2).*B.^3+p(3).*B.^2+p(4).*B+p(5);
Tsv(i)=4*rotp(1,l);
%px1 = linspace(h*(Index(l)-d-1),h*(Index(l)+d-2));
px1 = BB;
py1 = polyval(p,px1(1,l));
px = [px px1];
py = [py py1];
end
% Plots the max points
figure(1)
plot(px1(1),py(1),'b*-',px1(2),py(2),'b*-',px1(3),py(3),'b*-')
hold on
disp(Imax)

Your polyfit line should read:
p = polyfit(Area,I(l, Index(l)-2:Index(l)+2),4);
More interestingly, take note of the warnings you get about poor conditioning of that polynomial (I presume you're seeing these). Why? Partly because of numerical precision (your numbers are very small, scaled around 10^-6) and partly because you're asking for a 4th-order fit to five points (which is singular). To do this "better", use more input points (more than 5), or a lower-order polynomial fit (quadratic is usually plenty), and (probably) rescale before you use the polyfit tool.
Having said that, in practice this problem is often solved using three points and a quadratic fit, because it's computationally cheap and gives very nearly the same answers as more complex approaches, but you didn't get that from me (with noiseless data like this, it doesn't much matter anyway).

Related

FastICA Implementation.. Matlab

I have been working on a FastICA algorithm implementation using MatLab. Currently the code does not separate the signals as good as id like. I was wondering if anyone here could give me some advice on what I could do to fix this problem?
disp('*****Importing Signals*****');
s = [1,30000];
[m1,Fs1] = audioread('OSR_us_000_0034_8k.wav', s);
[f1,Fs2] = audioread('OSR_us_000_0017_8k.wav', s);
ss = size(f1,1);
n = 2;
disp('*****Mixing Signals*****');
A = randn(n,n); %developing mixing matrix
x = A*[m1';f1']; %A*x
m_x = sum(x, n)/ss; %mean of x
xx = x - repmat(m_x, 1, ss); %centering the matrix
c = cov(x');
sq = inv(sqrtm(c)); %whitening the data
x = c*xx;
D = diff(tanh(x)); %setting up newtons method
SD = diff(D);
disp('*****Generating Weighted Matrix*****');
w = randn(n,1); %Random weight vector
w = w/norm(w,2); %unit vector
w0 = randn(n,1);
w0 = w0/norm(w0,2); %unit vector
disp('*****Unmixing Signals*****');
while abs(abs(w0'*w)-1) > size(w,1)
w0 = w;
w = x*D(w'*x) - sum(SD'*(w'*x))*w; %perform ICA
w = w/norm(w, 2);
end
disp('*****Output After ICA*****');
sound(w'*x); % Supposed to be one of the original signals
subplot(4,1,1);plot(m1); title('Original Male Voice');
subplot(4,1,2);plot(f1); title('Original Female Voice');
subplot(4,1,4);plot(w'*x); title('Post ICA: Estimated Signal');
%figure;
%plot(z); title('Random Mixed Signal');
%figure;
%plot(100*(w'*x)); title('Post ICA: Estimated Signal');
Your covariance matrix c is 2 by 2, you cannot work with that. You have to mix your signal multiple times with random numbers to get anywhere, because you must have some signal (m1) common to different channels. I was unable to follow through your code for fast-ICA but here is a PCA example:
url = {'https://www.voiptroubleshooter.com/open_speech/american/OSR_us_000_0034_8k.wav';...
'https://www.voiptroubleshooter.com/open_speech/american/OSR_us_000_0017_8k.wav'};
%fs = 8000;
m1 = webread(url{1});
m1 = m1(1:30000);
f1 = webread(url{2});
f1 = f1(1:30000);
ss = size(f1,1);
n = 2;
disp('*****Mixing Signals*****');
A = randn(50,n); %developing mixing matrix
x = A*[m1';f1']; %A*x
[www,comp] = pca(x');
sound(comp(:,1)',8000)

How to vectorize a matlab script converting a 3d matrix to a single vector?

I am writing a graphical representation of numerical stability of differential operators and I am having trouble removing a nested for loop. The code loops through all entries in the X,Y, plane and calculates the stability value for each point. This is done by finding the roots of a polynomial of a size dependent on an input variable (length of input vector results in a polynomial 3d matrix of size(m,n,(lenght of input vector)). The main nested for loop is as follows.
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
The full code of an example numerical method (Trapezoidal Rule) is as follows. Any and all help is appreciated.
alpha = [-1 1];
beta = [.5 .5];
Wind = 2;
Wsize = 500;
if numel(Wind) == 1
Wind(4) = Wind(1);
Wind(3) = -Wind(1);
Wind(2) = Wind(4);
Wind(1) = Wind(3);
end
if numel(Wsize) == 1
Wsize(2) = Wsize;
end
z1 = linspace(Wind(1),Wind(2),Wsize(1));
z2 = linspace(Wind(3),Wind(4),Wsize(2));
[Z1,Z2] = meshgrid(z1,z2);
z = Z1+1i*Z2;
p = zeros(Wsize(2),Wsize(1),length(alpha));
for n = length(alpha):-1:1
p(:,:,(length(alpha)-n+1)) = alpha(n)-z*beta(n);
end
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
figure()
surf(Z1,Z2,z,'EdgeColor','None');
caxis([0 2])
cmap = jet(255);
cmap((127:129),:) = 0;
colormap(cmap)
view(2);
title(['Alpha Values (',num2str(alpha),') Beta Values (',num2str(beta),')'])
EDIT::
I was able to remove one of the for loops using the reshape command. So;
for m = 1:length(z2)
for n = 1:length(z1)
pointpoly(1,:) = p(m,n,:);
r = roots(pointpoly);
if isempty(r),r=1e10;end
z(m,n) = max(abs(r));
end
end
has now become
gg = reshape(p,[numel(p)/length(alpha) length(alpha)]);
r = zeros(numel(p)/length(alpha),1);
for n = 1:numel(p)/length(alpha)
temp = roots(gg(n,:));
if isempty(temp),temp = 0;end
r(n,1) = max(abs(temp));
end
z = reshape(r,[Wsize(2),Wsize(1)]);
This might be one for loop, but I am still going through the same number of elements. Is there a way to use the roots command on all of my rows at the same time?

Working on Separable Gabor filters in matlab

A filter g is called separable if it can be expressed as the multiplication of two vectors grow and gcol . Employing one dimensional filters decreases the two dimensional filter's computational complexity from O(M^2 N^2) to O(2M N^2) where M and N are the width (and height) of the filter mask and the image respectively.
In this stackoverflow link, I wrote the equation of a Gabor filter in the spatial domain, then I wrote a matlab code which serves to create 64 gabor features.
According to the definition of separable filters, the Gabor filters are parallel to the image axes - theta = k*pi/2 where k=0,1,2,etc.. So if theta=pi/2 ==> the equation in this stackoverflow link can be rewritten as:
The equation above is extracted from this article.
Note: theta can be extented to be equal k*pi/4. By comparing to the equation in this stackoverflow link, we can consider that f= 1 / lambda.
By changing my previous code in this stackoverflow link, I wrote a matlab code to make the Gabor filters separable by using the equation above, but I am sure that my code below is not correct especially when I initialized the gbp and glp equations. That is why I need your help. I will appreciate your help very much.
Let's show now my code:
function [fSiz,filters1,filters2,c1OL,numSimpleFilters] = init_gabor(rot, RF_siz)
image=imread('xxx.jpg');
image_gray=rgb2gray(image);
image_gray=imresize(image_gray, [100 100]);
image_double=double(image_gray);
rot = [0 45 90 135]; % we have four orientations
RF_siz = [7:2:37]; %we get 16 scales (7x7 to 37x37 in steps of two pixels)
minFS = 7; % the minimum receptive field
maxFS = 37; % the maximum receptive field
sigma = 0.0036*RF_siz.^2 + 0.35*RF_siz + 0.18; %define the equation of effective width
lambda = sigma/0.8; % it the equation of wavelength (lambda)
G = 0.3; % spatial aspect ratio: 0.23 < gamma < 0.92
numFilterSizes = length(RF_siz); % we get 16
numSimpleFilters = length(rot); % we get 4
numFilters = numFilterSizes*numSimpleFilters; % we get 16x4 = 64 filters
fSiz = zeros(numFilters,1); % It is a vector of size numFilters where each cell contains the size of the filter (7,7,7,7,9,9,9,9,11,11,11,11,......,37,37,37,37)
filters1 = zeros(max(RF_siz),numFilters);
filters2 = zeros(numFilters,max(RF_siz));
for k = 1:numFilterSizes
for r = 1:numSimpleFilters
theta = rot(r)*pi/180;
filtSize = RF_siz(k);
center = ceil(filtSize/2);
filtSizeL = center-1;
filtSizeR = filtSize-filtSizeL-1;
sigmaq = sigma(k)^2;
for x = -filtSizeL:filtSizeR
fx = exp(-(x^2)/(2*sigmaq))*cos(2*pi*x/lambda(k));
f1(x+center,1) = fx;
end
for y = -filtSizeL:filtSizeR
gy = exp(-(y^2)/(2*sigmaq));
f2(1,y+center) = gy;
end
f1 = f1 - mean(mean(f1));
f1 = f1 ./ sqrt(sum(sum(f1.^2)));
f2 = f2 - mean(mean(f2));
f2 = f2 ./ sqrt(sum(sum(f2.^2)));
p = numSimpleFilters*(k-1) + r;
filters1(1:filtSize,p)=f1;
filters2(p,1:filtSize)=f2;
convv1=imfilter(image_double, filters1(1:filtSize,p),'conv');
convv2=imfilter(double(convv1), filters2(p,1:filtSize),'conv');
figure
imagesc(convv2);
colormap(gray);
end
end
I think the code is correct provided your previous version of Gabor filter code is correct too. The only thing is that if theta = k * pi/4;, your formula here should be separated to:
fx = exp(-(x^2)/(2*sigmaq))*cos(2*pi*x/lambda(k));
gy = exp(-(G^2 * y^2)/(2*sigmaq));
To be consistent, you may use
f1(1,x+center) = fx;
f2(y+center,1) = gy;
or keep f1 and f2 as it is but transpose your filters1 and filters2 thereafter.
Everything else looks good to me.
EDIT
My answer above works for theta = k * pi/4;, with other angles, based on your paper,
x = i*cos(theta) - j*sin(theta);
y = i*sin(theta) + j*cos(theta);
fx = exp(-(x^2)/(2*sigmaq))*exp(sqrt(-1)*x*cos(theta));
gy = exp(-(G^2 * y^2)/(2*sigmaq))*exp(sqrt(-1)*y*sin(theta));
The final code will be:
function [fSiz,filters1,filters2,c1OL,numSimpleFilters] = init_gabor(rot, RF_siz)
image=imread('xxx.jpg');
image_gray=rgb2gray(image);
image_gray=imresize(image_gray, [100 100]);
image_double=double(image_gray);
rot = [0 45 90 135];
RF_siz = [7:2:37];
minFS = 7;
maxFS = 37;
sigma = 0.0036*RF_siz.^2 + 0.35*RF_siz + 0.18;
lambda = sigma/0.8;
G = 0.3;
numFilterSizes = length(RF_siz);
numSimpleFilters = length(rot);
numFilters = numFilterSizes*numSimpleFilters;
fSiz = zeros(numFilters,1);
filters1 = zeros(max(RF_siz),numFilters);
filters2 = zeros(numFilters,max(RF_siz));
for k = 1:numFilterSizes
for r = 1:numSimpleFilters
theta = rot(r)*pi/180;
filtSize = RF_siz(k);
center = ceil(filtSize/2);
filtSizeL = center-1;
filtSizeR = filtSize-filtSizeL-1;
sigmaq = sigma(k)^2;
for x = -filtSizeL:filtSizeR
fx = exp(-(x^2)/(2*sigmaq))*exp(sqrt(-1)*x*cos(theta));
f1(1, x+center) = fx;
end
for y = -filtSizeL:filtSizeR
gy=exp(-(y^2)/(2*sigmaq))*exp(sqrt(-1)*y*sin(theta));
f2(y+center,1) = gy;
end
f1 = f1 - mean(mean(f1));
f1 = f1 ./ sqrt(sum(sum(f1.^2)));
f2 = f2 - mean(mean(f2));
f2 = f2 ./ sqrt(sum(sum(f2.^2)));
p = numSimpleFilters*(k-1) + r;
filters1(1:filtSize,p)=f1;
filters2(p,1:filtSize)=f2;
convv1=imfilter(image_double, filters1(1:filtSize,p),'conv');
convv2=imfilter(double(convv1), filters2(p,1:filtSize),'conv');
figure
imagesc(imag(convv2));
colormap(gray);
end
end

How to stop MATLAB from rounding extremely small values to 0?

I have a code in MATLAB which works with very small numbers, for example, I have values that are on the order of 10^{-25}, however when MATLAB does the calculations, the values themselves are rounded to 0. Note, I am not referring to format to display these extra decimals, but rather the number itself is changed to 0. I think the reason is because MATLAB, by default, uses up to 15 digits after the decimal point for its calculations. How can I change this so that numbers that are very very small are retained as they are in the calculations?
EDIT:
My code is the following:
clc;
clear;
format long;
% Import data
P = xlsread('Data.xlsx', 'P');
d = xlsread('Data.xlsx', 'd');
CM = xlsread('Data.xlsx', 'Cov');
Original_PD = P; %Store original PD
LM_rows = size(P,1)+1; %Expected LM rows
LM_columns = size(P,2); %Expected LM columns
LM_FINAL = zeros(LM_rows,LM_columns); %Dimensions of LM_FINAL
for ii = 1:size(P,2)
P = Original_PD(:,ii);
% c1, c2, ..., cn, c0, f
interval = cell(size(P,1)+2,1);
for i = 1:size(P,1)
interval{i,1} = NaN(size(P,1),2);
interval{i,1}(:,1) = -Inf;
interval{i,1}(:,2) = d;
interval{i,1}(i,1) = d(i,1);
interval{i,1}(i,2) = Inf;
end
interval{i+1,1} = [-Inf*ones(size(P,1),1) d];
interval{i+2,1} = [d Inf*ones(size(P,1),1)];
c = NaN(size(interval,1),1);
for i = 1:size(c,1)
c(i,1) = mvncdf(interval{i,1}(:,1),interval{i,1}(:,2),0,CM);
end
c0 = c(size(P,1)+1,1);
f = c(size(P,1)+2,1);
c = c(1:size(P,1),:);
b0 = exp(1);
b = exp(1)*P;
syms x;
eqn = f*x;
for i = 1:size(P,1)
eqn = eqn*(c0/c(i,1)*x + (b(i,1)-b0)/c(i,1));
end
eqn = c0*x^(size(P,1)+1) + eqn - b0*x^size(P,1);
x0 = solve(eqn);
x0 = double(x0);
for i = 1:size(x0)
id(i,1) = isreal(x0(i,1));
end
x0 = x0(id,:);
x0 = x0(x0 > 0,:);
clear x;
for i = 1:size(P,1)
x(i,:) = (b(i,1) - b0)./(c(i,1)*x0) + c0/c(i,1);
end
% x = [x0 x1 ... xn]
x = [x0'; x];
x = x(:,sum(x <= 0,1) == 0);
% lamda
lamda = -log(x);
LM_FINAL(:,ii) = lamda;
end
The problem is in this step:
for i = 1:size(P,1)
x(i,:) = (b(i,1) - b0)./(c(i,1)*x0) + c0/c(i,1);
end
where the "difference" gets very close to 0. How can I stop this rounding from occurring at this step?
For example, when i = 10, I have the following values:
b_10 = 0.006639735483297
b_0 = 2.71828182845904
c_10 = 0.000190641848119641
c_0 = 0.356210110252579
x_0 = 7.61247930625269
After doing the calculations we get: -1868.47805854794 + 1868.47805854794 which yields a difference of -2.27373675443232E-12, that gets rounded to 0 by MATLAB.
EDIT 2:
Here is my data file which is used for the code. After you run the code (should take about a minute and half to finish running), row 11 in the variable x shows 0 (even after double clicking to check it's real value), when it shouldn't.
The problem you're having is because the IEEE standard for floating points can't distinguish your numbers from zero because they don't utilize sufficient bits.
Have a look at John D'Errico's Big Decimal Class and Variable Precision Integer Arithmetic. Another option would be to use the Big Integer Class from Java but that might be more challenging if you are unfamiliar with using Java and othe rexternal libraries in MATLAB.
Can you give an example of the calculations in which you are using 1e-25 and getting zero? Here's what I get for a floating point called small_num and one of John's high-precision-floats called small_hpf when assigning them and multiplying by pi.
>> small_num = 1e-25
small_num =
1.0000e-25
>> small_hpf = hpf(1e-25)
small_hpf =
1.000000000000000038494869749191839081371989361591338301396127644e-25
>> small_num * pi
ans =
3.1416e-25
>> small_hpf * pi
ans =
3.141592653589793236933163473501228686498684350685747717239459106e-25

Why do I get so many eigenvalues of zero in my Matlab eigenfaces implementation?

I'm trying to implement a very basic eigenface calculation in Matlab. It kind of works but I get only two meaningful eigenvalues - the rest are zero. The corresponding eigenvectors seem to be right since most of them will show an eigenface when converting to an image.
So why are most of my eigenvalues zero? I need them to be different from zero in order to sort the eigenfaces by their significance (greatest magnitude eigenvalues).
I am reading 400 images, each size h/w = 112/92 px
They can be found here: http://www.cl.cam.ac.uk/Research/DTG/attarchive/pub/data/att_faces.zip
The code:
clear all;
files = dir('eigenfaces2/training/*.pgm');
[numFaces, discard] = size(files);
h = 112;
w = 92;
s = h * w;
%calculate average face
avgFace = zeros(s, 1);
faces = [];
for i=1:numFaces
file = strcat('eigenfaces2/training/', files(i).name);
im = double(imread(file));
im = reshape(im, s, 1);
avgFace = avgFace + im;
faces(:,i) = im;
end
avgFace = avgFace ./ numFaces;
A = [];
for i=1:numFaces
diff = avgFace - faces(i);
A(:,i) = diff;
end
numEigs = 20;
L = (A' * A) / numFaces;
[tmpEigs, discard] = eigs(L, numEigs);
eigenfaces = [];
for i=1:numEigs
v = tmpEigs(:,i);
eigenfaces(:,i) = A * v;
end
%visualize largest eigenfaces
figure;
for i=1:numEigs
eigface = eigenfaces(:,i);
mmax = max(eigface);
mmin = min(eigface);
eigface = 255 .* (eigface-mmin) ./ (mmax-mmin);
eigface = reshape(eigface, h, w);
subplot(4,5,i); imshow(uint8(eigface));
end
I've don't have much experience with computer vision/image recognition, but I think you might want
diff = avgFace - faces(:,i);
in your second for loop. Otherwise it's just subtracting a constant from avgFace each time, and so A (and hence L) only gets a rank of 2.