Mr.WorshipMe
Mr.WorshipMe

Reputation: 763

Difference between OpenCV and Matlab implementing signal correlation using DFT

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

Answers (1)

Mr.WorshipMe
Mr.WorshipMe

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

Related Questions