Reputation: 763
I get sensible results using the Matlab code, but when translating it into OpenCV, I get wierd numbers which make no sense... I've looked at it for far too long and haven't found the bug, maybe you could?
Matlab implementation:
function [ score ] = getSimilarityScore( sig1, sig2, delta )
%%Calculate how much the signals are alike allowing a delta of shift.
%signal is assumed to be normalized such that it's elements sum is 1, sig1 and sig2 have the same number of elements.
sig1fft = fft(sig1);
sig1fft(1) = 0; %zero-out dc
sig2fft = fft(sig2);
sig2fft(1) = 0; %zero-out dc
%Should be the same as multiplying the signal by itself, and subtracting the mean times the number of element. could have just looked at the first element for the max...
norm1 = max(real(ifft(hist1fft.*conj(hist1fft))));
norm2 = max(real(ifft(hist2fft.*conj(hist2fft))));
corrConv = fftshift(real(ifft(hist1fft.*conj(hist2fft))));
corrConv((length(corrConv)/2 - delta):(length(corrConv)/2 + delta))
score = max(corrConv((length(corrConv)/2 - delta):(length(corrConv)/2 + delta)))/sqrt(norm1*norm2);
end
OpenCV (Java wraper)
public double getMaxCorrelationScoreUsingFFT(Mat sig1, Mat sig2, int allowedDelta)
{
Mat dft1 = new Mat(), dft2 = new Mat(), dftCorr = new Mat();
Core.dft(sig1,dft1,Core.DFT_COMPLEX_OUTPUT,0);
Core.dft(sig2,dft2,Core.DFT_COMPLEX_OUTPUT,0);
float [] zeroFreq = {0,0};
dft1.put(0,0,zeroFreq); //remove dc
dft2.put(0,0,zeroFreq); //remove dc
Core.mulSpectrums(dft1,dft2,dftCorr,0,true);
Core.mulSpectrums(dft1,dft1,dft1,0,true);
Core.mulSpectrums(dft2,dft2,dft2,0,true);
Core.dft(dft1,dft1,Core.DFT_INVERSE + Core.DFT_REAL_OUTPUT,0);
Core.dft(dft2,dft2,Core.DFT_INVERSE + Core.DFT_REAL_OUTPUT,0);
Core.dft(dftCorr,dftCorr,Core.DFT_INVERSE + Core.DFT_REAL_OUTPUT, 0);
double [] norm1, norm2;
norm1 = dft1.get(0,0);
norm2 = dft2.get(0,0);
if (norm1[0] == 0 || norm2[0] == 0)
if (norm1[0] != norm2[0])
return -1;
else
return 1;
//get -delta:delta range:
Mat fftShifted = new Mat(allowedDelta*2 + 1,1,CvType.CV_32F);
dftCorr.rowRange(dftCorr.height()/2 + 1,dftCorr.height()/2 + allowedDelta + 1).copyTo(fftShifted.rowRange(0,allowedDelta));
dftCorr.rowRange(0,allowedDelta+1).copyTo(fftShifted.rowRange(allowedDelta,fftShifted.height()));
Core.MinMaxLocResult minmaxCorr = Core.minMaxLoc(fftShifted);
return minmaxCorr.maxVal / Math.sqrt(norm1[0] * norm2[0]);
}
I'd be grateful if anyone could find what's different between the two implementations...
Upvotes: 0
Views: 151
Reputation: 763
Problem was with the fftshift code:
should be
dftCorr.rowRange(dftCorr.height() -allowedDelta,dftCorr.height()).copyTo(fftShifted.rowRange(0,allowedDelta));
instead of
dftCorr.rowRange(dftCorr.height()/2 + 1,dftCorr.height()/2 + allowedDelta + 1).copyTo(fftShifted.rowRange(0,allowedDelta));
Upvotes: 1