1

How can I divide a complex Mat with a real Mat in OpenCV? I want to calculate cross-power spectrum for phase correlation but I get a runtime error when using divide.

Update I figured out a way to calculate cross-power spectrum but i don't get the appropriate result to find the translation of an image. Below is the code. I split the result of inverse dft because it has two channels. Then, I was able to divide but the result is not good for translation only in the horizontal axis. There should be only one max value, but there are a lot of max values.

Image

void computeFFTMag(Mat&,Mat&,Mat&);
string getImgType(int );

int main( int argc, char** argv )
{
    Mat ref,sens,refMag,sensMag,refFFT,sensFFT;
    ref = imread("lena1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
    sens = imread("lena3.jpg",CV_LOAD_IMAGE_GRAYSCALE);


    namedWindow( "Sensed Image", CV_WINDOW_AUTOSIZE );
    imshow( "Sensed Image", sens );

    computeFFTMag(ref,refMag,refFFT);
    computeFFTMag(sens,sensMag,sensFFT);


    Mat R1,R2,R,r,rf[2],rff;
    mulSpectrums(refFFT,sensFFT,R1,0,true);
    multiply(refMag,sensMag,R2);
    dft(R1,r,DFT_REAL_OUTPUT);
    split(r,rf);
    divide(rf[0],R2,r);
    normalize(r, r, 0, 1, CV_MINMAX);
    namedWindow( "Reference Image", CV_WINDOW_AUTOSIZE );
    imshow("Reference Image"       , r   );
}



void computeFFTMag(Mat& input,Mat& fftMag,Mat& complexFFT){
    Mat inputPadded;
    /*int r=getOptimalDFTSize(input.rows);
    int c=getOptimalDFTSize(input.cols);
    copyMakeBorder(input,inputPadded,0,r-input.rows,0,c-input.cols,BORDER_CONSTANT, Scalar::all(0));*/
    Mat fftPlanes[] = {Mat_<float>(input), Mat::zeros(input.size(), CV_32F)};
    //Mat complexFFT;
    merge(fftPlanes, 2, complexFFT);

    dft(complexFFT,complexFFT);
    split(complexFFT,fftPlanes);
    magnitude(fftPlanes[0],fftPlanes[1],fftPlanes[0]);

    fftMag=fftPlanes[0];

    //fftMag = fftMag(Rect(0, 0, fftMag.cols & -2, fftMag.rows & -2));
    int cx = fftMag.cols/2;
    int cy = fftMag.rows/2;
    Mat q0(fftMag, Rect(0, 0, cx, cy));   // Top-Left - Create a ROI per quadrant
    Mat q1(fftMag, Rect(cx, 0, cx, cy));  // Top-Right
    Mat q2(fftMag, Rect(0, cy, cx, cy));  // Bottom-Left
    Mat q3(fftMag, Rect(cx, cy, cx, cy)); // Bottom-Right

    Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);

    q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
    q2.copyTo(q1);
    tmp.copyTo(q2);
}

1 Answers1

0

A complex number can be divided by a scalar by dividing the real and complex terms by the same scalar. So, (2 + 3i) / 4 is equal to 2/4 + (3/4)i.

OpenCV doesn't let you do elementwise division of complex mats with scalar mats, but it does let you do elementwise division of complex mats with complex mats. You can get the division to work by creating a complex matrix where both the real and imaginary components are the same as the real values in your real mat that you want to divide by.

// Goal: Divide 'complex' by 'real'
Mat complex = Mat(rows, cols, CV_32FC2);
Mat real = Mat(rows, cols, CV_32FC1);

Mat channels[2] = {real, real};
Mat divisor = Mat(rows, cols, CV_32FC2);
merge(channels, 2, divisor);

Mat result = Mat(rows, cols, CV_32FC2); 
divide(complex, divisor, result);
Lemons
  • 379
  • 4
  • 14