I'm trying to convert this simple Matlab code to C++ with openCV:
localstd=sqrt(abs(ifft2(fft2(output).*gf)));
It means taking the fft of the matrix "output", multiplying it element by element with the matrix "gf", then taking the ifft of that and then taking the magnitude of that.
I'm trying the following simple code:
Mat complexI;
dft(output, complexI,cv::DFT_SCALE||DFT_COMPLEX_OUTPUT);
Mat copmlexI2=Mat(n,n,CV_32F);
mulSpectrums(complexI,gf,copmlexI2,DFT_COMPLEX_OUTPUT);
dft(copmlexI2,copmlexI2,cv::DFT_INVERSE||DFT_COMPLEX_OUTPUT);
Mat planes[]= {Mat::zeros(output.size(), CV_32F), Mat::zeros(output.size(), CV_32F)};;
split(copmlexI2, planes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I))
magnitude(planes[0], planes[1], planes[0]);// planes[0] = magnitude
Mat localstd = planes[0];
for (int i=0;i<localstd.rows;i++){
for (int j=0;j<localstd.cols;j++){
localstd.at<float>(i,j)= sqrt(localstd.at<float>(i,j));
}
}
for (int i=0;i<localstd.rows;i++){
for (int j=0;j<localstd.cols;j++){
localstd.at<float>(i,j)/= 255;
}
}
It's very simple. I'm taking the dft of "output", multiply it's spectrum with "df" and take the ifft of that. Next, I split the result into the real and imaginary plane and take the magnitude. Finally, I take the sqrt of that and normalize by dividing with 255.
The results I get are very different than what I get in Matlab. What am I missing here? Any ideas on how to fix the code?
Thanks in advance!
This is not correct
cv::DFT_INVERSE||DFT_COMPLEX_OUTPUT
, if you want combine binary values you should use "binary or":
cv::DFT_INVERSE | DFT_COMPLEX_OUTPUT
or + operation
cv::DFT_INVERSE + DFT_COMPLEX_OUTPUT
A || B - is logical or. A, B and result may be only true or false.
A | B - is bitwise or.
You can also try DFT_SCALE flag.
DFT_SCALE scales the result: divide it by the number of array
elements. Normally, it is combined with DFT_INVERSE.
Related
I am trying to check convolution theorem in MATLAB. I have a signal called sine_big_T. Then I have a filter called W. W and sine_big_T have the same length.
The convolution theorem says that fft(sine_big_T.*W) should be same as the convolution of fft(sine_big_T) with fft(W).
I am quite confused about this theorem. fft(sine_big_T.*W) will give me a array with length length(sine_big_T). However, conv(fft(sine_big_T), fft(W)) gives me a array with length length(sine_big_T) + length(W) - 2. I have tried the commend conv(fft(sine_big_T), fft(W), 'same'), but the result is still much different from fft(sine_big_T.*W).
T = 128;
big_T = 8*T;
small_T = T/8;
sine_big_T = zeros(1,129);
sine_small_T = zeros(1,129);
W = zeros(1,129);
for i = 0:T
sine_big_T(1, i+1) = sin(2*pi/big_T*i);
W(1, i + 1) = 1 - cos(2*pi/T * i);
end
figure
plot(1:129,fft(sine_big_T.*W));
I_fft = fft(sine_big_T);
W_fft = fft(W);
test = conv(I_fft, W_fft,'same');
figure
plot(1:length(I_fft), test)
From the theorem, the two plots should look same. But the result is not even close. I think the way I use conv is not correct. What is the right way to verify the theorem?
Using conv with 'same' is correct. You are seeing two things:
fft defines the origin in the first array element, not the middle of the domain. This does not play well with conv. Use this instead:
test = ifftshift( conv( fftshift(I_fft), fftshift(W_fft), 'same' ) );
The fftshift function shifts the origin to the middle of the array, where it is good for conv with 'same', and ifftshift shifts the origin back to the first element.
Normalization. The FFT is typically normalized so that multiplication in the frequency domain is convolution in the spatial domain. Since you are computing convolution in the frequency domain, the normalization is off. To correct the normalization, plot
plot(1:129,fft(sine_big_T.*W)*length(W));
I want to use GPU to speed up my matlab program but I find out a problem.
The fft result is different from CUDA to matlab.
I have tried many time but can't solve it.
So I come here for help.
The original data: name:cj1;size:1*8
And in matlab use the code:
a1=fft(cj1)';
Get the result:
the fft result of matlab
And cuda code:
cuFloatComplex *idata_m;
idata_m = (cuFloatComplex*)malloc(M * sizeof(cuFloatComplex));
for (int i = 0; i < 8; i++)
{
idata_m[i].x = initA[i];
idata_m[i].y = initB[i];
}
cuComplex *dev_test;
cudaMalloc((void**)&dev_test, M * sizeof(cuFloatComplex));
cudaMemcpy(dev_test, idata_m, M * sizeof(cuFloatComplex), cudaMemcpyHostToDevice);
cufftHandle plantest;
cufftPlan1d(&plantest, 8, CUFFT_C2C, 1);
cufftExecC2C(plantest, dev_test, dev_test, CUFFT_FORWARD);//forward
cuComplex *test_out;
test_out = (cuFloatComplex*)malloc( M * sizeof(cuFloatComplex));
cudaMemcpy(test_out, dev_test, 8 * sizeof(cuFloatComplex), cudaMemcpyDeviceToHost);
the input data is the same to the original data in matlab
the fft result of cuda
the inserest thing is these two result are very similar but in the wrong order.
So what can I do to make the result the same to the result of matlab?
The imaginary part of the input data used with the CUDA code is the negative of that used with Matlab. So you really are computing the FFT of the complex conjugated input, which inverts the order of the result. To obtain the same results with CUDA you should be using the same input.
Also of note, in Matlab, the ' operator computes the complex-conjugate transpose, so you probably want to compare your CUDA results with a1=transpose(fft(cj1)); instead.
i am trying to calculate the inverse fourier transform of the vector XRECW. for some reason i get a vector of NANs.
please help!!
t = -2:1/100:2;
x = ((2/5)*sin(5*pi*t))./((1/25)-t.^2);
w = -20*pi:0.01*pi:20*pi;
Hw = (exp(j*pi.*(w./(10*pi)))./(sinc(w./(10*pi)))).*(heaviside(w+5*pi)-heaviside(w-5*pi));%low pass filter
xzohw = 0;
for q=1:20:400
xzohw = xzohw + x(q).*(2./w).*sin(0.1.*w).*exp(-j.*w*0.2*((q-1)/20)+0.5);%calculating fourier transform of xzoh
end
xzohw = abs(xzohw);
xrecw = abs(xzohw.*Hw);%filtering the fourier transform high frequencies
xrect=0;
for q=1:401
xrect(q) = (1/(2*pi)).*trapz(xrecw.*exp(j*w*t(q))); %inverse fourier transform
end
xrect = abs(xrect);
plot(t,xrect)
Here's a direct answer to your question of "why" there is a nan. If you run your code, the Nan comes from dividing by zero in line 7 for computing xzohw. Notice that w contains zero:
>> find(w==0)
ans =
2001
and you can see in line 7 that you divide by the elements of w with the (2./w) factor.
A quick fix (although it is not a guarantee that your code will do what you want) is to avoid including 0 in w by using a step which avoids zero. Since pi is certainly not divisible by 100, you can try taking steps in .01 increments:
w = -20*pi:0.01:20*pi;
Using this, your code produces a plot which might resemble what you're looking for. In order to do better, we might need more details on exactly what you're trying to do, or what these variables represent.
Hope this helps!
I'm Very new to opencv.I need to convert the code from matlab to opencv.i have problem with use fft in matlab.i have a one dimensional matrix a.and i'm going apply fft in that as given below.
a = [0;0;0;0;0;0;0;0;0.09707;0.0998;0.1202;-0.1606;-0.0913;0.1523;0.1288];
c = abs(fft(a,15));
c >> 0.3463
0.1056
0.3608
0.5705
0.4232
0.2407
0.1486
0.1488
0.1488
0.1486
0.2407
0.4232
0.5705
0.3608
0.1056
C is my result,which i got from matlab.while i'm going to use cvDFT for this one the results are differnt.please help me with some example..my c code is given below...
CvMat* fftin = cvCreateMat(nn,1,CV_64FC2);
CvMat* fftout = cvCreateMat(nn,1,CV_64FC2);
cvZero(b); ////consider a hav the value of mat b is empty for imgin
cvMerge(a,b,NULL,NULL,fftin);
cvDFT(fftin,fftout,CV_DXT_FORWARD,0);
cvSplit(fftout,out_real,out_img,0,0);
for (int i = 0;i<out_real->rows;i++)
{
double val11= cvGetReal2D(out_real,i,0);
double val12= cvGetReal2D(out_img,i,0);
val11 = abs(val11);
val12 = abs(val12);
printf("DFT value is:%f %f\n",val11,val12);
cvSetReal2D(C_out,i,0,val11);
}
In your first example, you seem to be printing the magnitude of each complex value in the result. But in your second example you seem to be printing the absolute value of each component of the complex values (e.g. X and Y instead of the length or hypotenuse).
I am asked to write an fft mix radix in matlab, but before that I want to let to do a discrete Fourier transform in a straight forward way. So I decide to write the code according to the formula defined as defined in wikipedia.
[Sorry I'm not allowed to post images yet]
http://en.wikipedia.org/wiki/Discrete_Fourier_transform
So I wrote my code as follows:
%Brutal Force Descrete Fourier Trnasform
function [] = dft(X)
%Get the size of A
NN=size(X);
N=NN(2);
%====================
%Declaring an array to store the output variable
Y = zeros (1, N)
%=========================================
for k = 0 : (N-1)
st = 0; %the dummy in the summation is zero before we add
for n = 0 : (N-1)
t = X(n+1)*exp(-1i*2*pi*k*n/N);
st = st + t;
end
Y(k+1) = st;
end
Y
%=============================================
However, my code seems to be outputting a result different from the ones from this website:
http://www.random-science-tools.com/maths/FFT.htm
Can you please help me detect where exactly is the problem?
Thank you!
============
Never mind it seems that my code is correct....
By default the calculator in the web link applies a window function to the data before doing the FFT. Could that be the reason for the difference? You can turn windowing off from the drop down menu.
BTW there is an FFT function in Matlab