Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct to pass frequency domain images to phase correlation? #10

Open
joelloo opened this issue Sep 9, 2020 · 3 comments
Open

Correct to pass frequency domain images to phase correlation? #10

joelloo opened this issue Sep 9, 2020 · 3 comments

Comments

@joelloo
Copy link

joelloo commented Sep 9, 2020

Hi,

Thanks for the well-written code! In my testing, it seems that it performs decently well. While trying to understand the code however, I noticed that you apply DFT to transform the images into the frequency domain, where you apply the highpass filter. Subsequently however, the log-polar transformation is applied directly on the frequency domain image, and the frequency domain image is passed into cv::phaseCorrelate. I have attached the section of code below for reference.

May I ask why the log-polar transformation and phaseCorrelate use the frequency domain image instead of the spatial domain image? I read the referenced papers (in particular [2]), and they seem to suggest using the spatial domain image instead. Moreover, cv::phaseCorrelate already seems to do a DFT inside, and so it seems like it should be taking in a spatial domain image instead. On the other hand the code does work in a number of test cases I tried, so I'm not sure if I'm missing some detail.

Thanks!

(For reference, I'm referring to this section)

    Mat F0[2], F1[2];
    Mat f0, f1;
    ForwardFFT(im0, F0);
    ForwardFFT(im1, F1);
    magnitude(F0[0], F0[1], f0);
    magnitude(F1[0], F1[1], f1);

    // Create filter 
    Mat h;
    highpass(f0.size(), h);

    // Apply it in freq domain
    f0 = f0.mul(h);
    f1 = f1.mul(h);

    float log_base;
    Mat f0lp, f1lp;

    log_base = logpolar(f0, f0lp);
    log_base = logpolar(f1, f1lp);

    // Find rotation and scale
    Point2d rotation_and_scale = cv::phaseCorrelate(f1lp, f0lp);
@Smorodov
Copy link
Owner

Smorodov commented Sep 9, 2020

Hi, it was so long ago )
As I see here, FFT moves objects from center (we may assume for small scale changes and not many spikes) when we scaling up the image and it conveys rotation as it is. Thus, transformin it to polar coordinates will produce the image, shifted along one coordinate according the scale change, and shifted (really true for a one quadrant, as I see now) along another one proportionally to rotation. Applying phase shift to these images will give shift between two frequency domain polar coordinates images and we will have scale and rotation estimation. But thanks for your question, now I think, that may be it will be correct to use only one quadrant of FFT image? Because scale will really also scale FFT wrt to center. And assumption that it moves objects from center is acceptable for a sector less than 90 deg only. May be the algorithm will work more robust if we will clear 3/4 of FFT image (or keep only the brightest points in small sector), will try, when will appear a bit of time.
Thanks for your question.

@Smorodov
Copy link
Owner

Smorodov commented Sep 9, 2020

Whithout FFT, phase correlation will give rotation and shift (scale must be the same).
With FFT it will give rotation and scale.

@Smorodov
Copy link
Owner

Smorodov commented Sep 9, 2020

Tested version with 3/4 of FFT cleaned before polar transformation, looks like it becomes less robust to rotation, scale and offset ranges.
UPD: really not necessary to clean 3/4 of images.
Check great illustration here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants