Simple Phase Shift for Removing Instrument Response - matlab

So I have a simple program where I want to shift a simple sine function pi/2. Now I knwo this would be extremely easy by just inserting a bias (i.e. A*sin(2*pi*frequency + bias). But this program is a simple way to test a theory. I need to shift complicated magnetic data, but the shift is frequency dependent. So to figure out how to do that I just want to shift this sin wave by a set shift, but I want to do it in the frequency domain. While the code below doesn't show any errors, it does not shift the data properly and effects magnitude. Code is below. Thank you!
clear all
time = 1:0.01:2*pi; %Create time vector
mag = sin(2*pi*time);
Y = fft(mag); %transform
Pnewr = pi/2;
%t = angle(mag);
t = imag(Y);
%t_fin = t-Pnewr; %Subtract the pahse delay from the original phase vector
R=real(Y);
I=t;
k = I./R
Phi = tan(k);
PhiFinal = Phi-Pnewr;
PhiFinal = PhiFinal'
IFinal = R * atan(PhiFinal);
spec=complex(R,IFinal);
Finalspec = ifft(spec); %Invert the transform
Final = Finalspec;
plot(time,mag);
hold on
plot(time,Final,'r')
grid on

For one thing you are not recombining imaginary and real components properly, since
PhiFinal = PhiFinal'
IFinal = R * atan(PhiFinal);
is effectively a dot product, not an element by element product. In general it doesn't look like you are making correct use of the complex relationships. The following generates a clean phase shift:
time = 1:0.01:2*pi;
mag = sin(2*pi*time);
Y = fft(mag); %transform
Pnewr = pi/2;
R = real(Y);
I = imag(Y);
It = abs(Y);
% It = sqrt(I.^2 + R.^2);
Phi= angle(Y); % <-- using matlab function, equivalent to `Phi = atan2(I, R);`
k = I./R;
Phi0 = atan(k);
figure, subplot(121), plot(Phi0,Phi,'.'), xlabel('Phi from tan'), ylabel('Phi from ''angle'''), grid on, axis('tight')
PhiFinal = Phi-Pnewr; % <-- phase shift
IFinal = It .* sin(PhiFinal);
RFinal = It .* cos(PhiFinal);
spec= RFinal + 1i*IFinal;
Final = ifft(spec); %Invert the transform
subplot(122)
plot(time,mag);
hold on
plot(time,real(Final),'r')
plot(time,imag(Final),'r:')
grid on
axis('tight')
legend('Initial','Final'),xlabel('t'), ylabel('I')
mag*mag' % <-- check that total power is conserved
Final*Final'
These figures show the phase as computed with tan vs matlab's angle (which uses atan2), and the results of the phase shift (right panel):

Related

How can I invert my temperature to display in the positive domain?

The experimental set up and analytical solution I am trying to solve a parabolic PDE with the pdepe function in MATLAB. The code runs fine, but the temperature is in the inverted direction when I use my boundary conditions as it is in the physical situation. I can interpret the results and it matches what I am looking for, but I want to be able to display the temperature in both the correct magnitude and direction. What am I missing?
I can swap the boundary surfaces, that is, swap x=0 and x=L, (while keeping the boundary conditions the same); and the temperature would be in the correct direction but the distance is now inverse.
L = 0.1524;
k = 0.0022;
cp = 1.92;
rho = 0.946;
tend = 18;
Flux = 1.1;
m = 0;
x = linspace(0,L,200);
t = linspace(0,tend,100);
sol = pdepe(m,#pdex1pde,#pdex1ic,#pdex1bc,x,t);
Temperature = sol(:,:,1);
surf(x,t,Temperature)
title('Surface Temperature')
xlabel('Distance x')
ylabel('Time t')
zlabel('Temperature (C)')
function [c,f,s] = pdex1pde(x,t,u,DuDx)
global rho cp k
c = rho*cp;
f = k*DuDx;
s = 0;
function [Temperature] = pdex1ic(x)
Temperature = 25;
function [pl,ql,pr,qr] = pdex1bc(xl,ul,xr,ur,t)
global Flux k
pl = 0;
ql = 1/k;
pr = Flux;
qr = 1;
The temperature is inverse. I expect a range up to 120, I'm getting a line that terminates at about -120.
The result of the numerical solution that shows the inverted temperature

Forecast future values from FFT

In the attached code I create an arbitrarily complex signal generator (3 sine waves in this case) and generate 256 + 50 values using it. I then create an FFT using the first 256 values, plot them and then do an inverse FFT and verify that it produces a very close representation of the original signal. All good so far.
What I'd like to do now is, using the FFT results, attempt to generate the additional 50 values that were not part of the FFT data set. Is there a straight-forward in MatLab?
Without being exactly sure how I assume I can create a signal generator using the center frequency of each bin and the FFT result and generate the signal that way, but that does seem like a lot of work so before I went down that path I figured I'd see if there was an easy way that I just haven't found.
I have MatLab & the Signal Processing and DSP packages to use at this time.
Thanks!
FFTsize = 256;
futureSize = 50;
t = 1:FFTsize+futureSize;
F1_bars = 10;
RadPerBar1 = (2*pi)/F1_bars;
L1 = 1;
Offset1 = 0;
F2_bars = 8;
RadPerBar2 = (2*pi)/F2_bars;
L2 = 1;
Offset2 = 0;
F3_bars = 50;
RadPerBar3 = (2*pi)/F3_bars;
L3 = 1;
Offset3 = 0;
Sig = (L1*sin(RadPerBar1*t + Offset1) +...
L2*sin(RadPerBar2*t + Offset2) +...
L3*sin(RadPerBar3*t + Offset3));
DataSet = Sig(1:FFTsize);
FFT = fft(DataSet)/FFTsize;
%Suggested by Mad Physicist
paddedFFT = [FFT(1:ceil(FFTsize/2)) zeros(1, futureSize) FFT(ceil(FFTsize/2)+1 : end)];
IFFT = ifft(FFT)*FFTsize;
%Suggested by Mad Physicist
IFFT2 = ifft(paddedFFT)*(FFTsize + futureSize);
figure(111);
hold off;
plot(abs(FFT));
hold on;
plot(abs(paddedFFT),'--r');
legend('FFT','Padded FFT','Position','best');
hold off;
figure(110)
hold off;
plot(Sig);
hold on;
plot(IFFT,'--r');
plot(t, IFFT2,'g');
legend('Input Signal','IFFT','Padded IFFT','Position','best');
hold off;
Pad the FFT with 50 zeros before you invert it:
futureSize = 50;
paddedFFT = [FFT(1:ceil(FFTsize/2)) zeros(1, futureSize) FFT(ceil(FFTsize/2)+1 : end)];
IFFT = ifft(paddedFFT)*(FFTsize + futureSize);

Local Histogram Separation Energy Implementation

I am working in level set method, specially Lankton method paper. I try to implement Histogram Separation (HS) Energy problem (Part III.C). It based on Bhattacharyya to control the evolution of contour. To understand it, the first we consider global method in which given an input image and a contour. The contour divides the image into inside and outside region. The Bhattacharyya distance is calculated by
B=sqrt (P_in.*P_out)
where P_in and P_pout are pdf of inside and outside regions.
To applied Bhattacharyya for global level set you can see source code at here. Now we return the Lankton paper. It is local level set. In which, he divides the image into small region by Ball function. Then, the contour will separate these regions into inside and outside region. Each small regions have P_in and P_out. And we can calculate Bhattacharyya distance. I done that step. But I cannot implement final step as formual. Can you help me???
and Av and Au is area of inside and outside of these regions. This is my main code. You can download at source code
for its = 1:max_its % Note: no automatic convergence test
%-- get the curve's narrow band
idx = find(phi <= 1.2 & phi >= -1.2)';
[y x] = ind2sub(size(phi),idx);
%-- get windows for localized statistics
xneg = x-rad; xpos = x+rad; %get subscripts for local regions
yneg = y-rad; ypos = y+rad;
xneg(xneg<1)=1; yneg(yneg<1)=1; %check bounds
xpos(xpos>dimx)=dimx; ypos(ypos>dimy)=dimy;
%-- re-initialize u,v,Ain,Aout
Ain=zeros(size(idx)); Aout=zeros(size(idx));
B=zeros(size(idx));integral=zeros(size(idx));
%-- compute local stats
for i = 1:numel(idx) % for every point in the narrow band
img = I(yneg(i):ypos(i),xneg(i):xpos(i)); %sub image
P = phi(yneg(i):ypos(i),xneg(i):xpos(i)); %sub phi
upts = find(P<=0); %local interior
Ain(i) = length(upts)+eps;
vpts = find(P>0); %local exterior
Aout(i) = length(vpts)+eps;
%% Bha distance
p = imhist(I(upts))/ Ain(i) + eps; % leave histograms unsmoothed
q = imhist(I(vpts)) / Aout(i) + eps;
B(i) = sum(sqrt(p.* q));
term2= sqrt(p./q)/Aout(i) - sqrt(q./p)/Ain(i); %Problem in here===I don't know how to code the integral term
integral(i) =sum(term2(:));
end
F =-B./2.*(1./Ain - 1./Aout) - integral./2;
I tried this - no idea if its correct - its has no histogram smoothing (I dont think it is necessary)
if type==3 % Set up for bhatt
F=zeros(size(idx,1),2);
for i = 1:numel(idx)
img2 = img(yneg(i):ypos(i),xneg(i):xpos(i));
P = phi(yneg(i):ypos(i),xneg(i):xpos(i));
upts = find(P<=0); %local interior
Ain = length(upts)+eps;
[u,~] = hist(img2(upts),1:256);
vpts = find(P>0); %local exterior
Aout = length(vpts)+eps;
[v,~] = hist(img2(vpts),1:256);
Ap = Ain;
Aq = Aout;
In=Ap;
Out=Aq;
try
p = ((u)) ./ Ap + eps;
q = ((v)) ./ Aq + eps;
catch
g
end
B = sum(sqrt(p .* q));
F(i)=B.*((1/numel(In))-(1/numel(Out)))+(0.5.*(1/numel(In)*(q(img(idx(i))+1)... /p(img(idx(i))+1))))-(0.5.*(1/numel(Out)*(p(img(idx(i))+1)/q(img(idx(i))+1))));
end

HOG descriptor for multiple people detection

I am doing a real-time people detection using HOG-LBP descriptor and using a sliding window approach for the detector also LibSVM for the classifier. However, after classifier I never get multiple detected people, sometimes is only 1 or might be none. I guess I have a problem on my classification step. Here is my code on classification:
label = ones(length(featureVector),1);
P = cell2mat(featureVector);
% each row of P' correspond to a window
% classifying each window
[~, predictions] = svmclassify(P', label,model);
% set the threshold for getting multiple detection
% the threshold value is 0.7
get_detect = predictions.*[predictions>0.6];
% the the value after sorted
[r,c,v]= find(get_detect);
%% Creating the bounding box for detection
for ix=1:length(r)
rects{ix}= boxPoint{r(ix)};
end
if (isempty(rects))
rects2=[];
else
rects2 = cv.groupRectangles(rects,3,'EPS',0.35);
end
for i = 1:numel(rects2)
rectangle('Position',[rects2{i}(1),rects2{i}(2),64,128], 'LineWidth',2,'EdgeColor','y');
end
For the whole my code, I have posted here : [HOG with SVM] (sliding window technique for multiple people detection)
I really need a help for it. Thx.
If you have problems wiith the sliding window, you can use this code:
topLeftRow = 1;
topLeftCol = 1;
[bottomRightCol bottomRightRow d] = size(im);
fcount = 1;
% this for loop scan the entire image and extract features for each sliding window
for y = topLeftCol:bottomRightCol-wSize(2)
for x = topLeftRow:bottomRightRow-wSize(1)
p1 = [x,y];
p2 = [x+(wSize(1)-1), y+(wSize(2)-1)];
po = [p1; p2];
img = imcut(po,im);
featureVector{fcount} = HOG(double(img));
boxPoint{fcount} = [x,y];
fcount = fcount+1;
x = x+1;
end
end
lebel = ones(length(featureVector),1);
P = cell2mat(featureVector);
% each row of P' correspond to a window
[~, predictions] = svmclassify(P',lebel,model); % classifying each window
[a, indx]= max(predictions);

Harmonic Product Spectrum using MATLAB

Im tying to find the fundamental frequency of a note using harmonic product spectrum. This is the part that implements the HPS algorithm
seg_fft = seg_fft(1 : size(seg_fft,1)/2 ); % FFT data
seg_fft = abs(seg_fft);
seg_fft2 = ones(size(seg_fft));
seg_fft3 = ones(size(seg_fft));
seg_fft4 = ones(size(seg_fft));
seg_fft5 = ones(size(seg_fft));
for i = 1:floor((length(seg_fft)-1)/2)
seg_fft2(i,1) = (seg_fft(2*i,1) + seg_fft((2*i)+1,1))/2;
end
for i = 1:floor((length(seg_fft)-2)/3)
seg_fft3(i,1) = (seg_fft(3*i,1) + seg_fft((3*i)+1,1) + seg_fft((3*i)+2,1))/3;
end
for i = 1:floor((length(seg_fft)-3)/4)
seg_fft4(i,1) = (seg_fft(4*i,1) + seg_fft((4*i)+1,1) + seg_fft((4*i)+2,1) + seg_fft((4*i)+3,1))/4;
end
for i = 1:floor((length(seg_fft)-4)/5)
seg_fft5(i,1) = (seg_fft(5*i,1) + seg_fft((5*i)+1,1) + seg_fft((5*i)+2,1) + seg_fft((5*i)+3,1) + seg_fft((5*i)+4,1))/5;
end
f_ym = (seg_fft) .* (seg_fft2) .* (seg_fft3) .* (seg_fft4) .*(seg_fft5);
Now when i play F4, the 2nd harmonic(698 -F5) has a higher amplitude. So HPS is supposed to help me detect the fundamental which is F4 and NOT F5.
When i do the HPS these are the graphs I get:
The figures above show the plots of seg_fft2, seg_fft3, seg_fft4 and seg_fft5 respectively.
But what I dont understand is how come the frequency points obtained in these graphs are not factors of the original spectrum?? Isn't that how HPS is supposed to work??
This is the plot I obtained when I took the product of all 5.
the peak is at 698Hz.. But shouldn't it be at 349Hz instead??
But after the whole code is run, I do get the fundamental as F4.. Its all very confusing.... Can someone tell me why my graphs are different from what is expected yet I get the correct fundamental please????
This is the rest of the code
%HPS, PartIII: find max
f_y1 = max(f_ym)
for c = 1 : length(f_ym)
if(f_ym(c,1) == f_y1)
index = c;
end
end
% Convert that to a frequency
f_y(h) = (index / NFFT) * FS;
h=h+1;
%end
V = abs(f_y);
Please do help...... Thanx in advance....