I want to calculate phase correlation of function in OpenCV. I’ve found http://nashruddin.com/phase-correlation-function-in-opencv.html but there is used some other library and I want to do it with OpenCV.
My problem is differen cause I want to calculate phase correlation of two arrays, both 360 elements.
I tried to evaluate from documentation how to do it, but I don’t know if my method is good.
My R matrix isn’t normalized, how to normalize it and is it necessary?
If you give me some examples I would be grateful.
My function to do this task:
void calcPhaseCorrelation(int* x1, int* x2){
Mat array1 = Mat(1,360,DataType<float>::type);
Mat array2 = Mat(1,360,DataType<float>::type);
uchar* begin = array1.data;
uchar* end = begin + (array1.step.p[0]/ sizeof(float)) * array1.size().height;
uchar *ptr = begin;
int ctr1 = 0, ctr2 = 0; //control in loops
while(ptr<end)
{
*ptr = (float)x1[ctr1];
ctr1++;
ptr++;
}
begin = array2.data;
end = begin + (array2.step.p[0]/ sizeof(float)) * array2.size().height;
ptr = begin;
while(ptr<end)
{
*ptr = x2[ctr2];
ctr2++;
ptr++;
}
Mat outputArray;
outputArray.create(abs(array1.rows - array2.rows)+1,
abs(array1.cols - array2.cols)+1, array1.type());
Size dftSize;
dftSize.width = getOptimalDFTSize(array1.cols + array2.cols - 1);
dftSize.height = getOptimalDFTSize(array1.rows + array2.rows - 1);
Mat resultA(dftSize, array1.type(), Scalar::all(0));
Mat resultB(dftSize, array2.type(), Scalar::all(0));
dft(array1,resultA);
dft(array2,resultB);
Mat R;
mulSpectrums(resultA,resultB,R,DFT_ROWS,true);
Mat NormR;
normalize(R,NormR);
idft(NormR,outputArray);
double minVal, maxVal;
Point minLoc, maxLoc;
minMaxLoc(outputArray,&minVal,&maxVal,&minLoc,&maxLoc);
std::cout<<"Min value: "<<minVal<<", max value: "<<maxVal<<std::endl;
std::cout<<"Min loc x: "<<minLoc.x<<", min loc y: "<<minLoc.y<<std::endl;
std::cout<<"Max loc x: "<<maxLoc.x<<", max loc y: "<<maxLoc.y<<std::endl;
}
I know that code is not clear etc., but it’s only fast test. I want to know if method is correct. But also there every advice is appreciated.
//Edit:
I used mevatron code and get #QNAN also while debugging seen that in function that it does not find a peak, value is (-1,-1).
Function I’m using with new OpenCV correlation function:
void phaseCorrelationOpenCvTrunk(int* array1, int* array2)
{
Mat hann;
vector<double> arr1, arr2;
for(int i = 0; i < 360; i++)
{
arr1.push_back((double)array1[i]);
arr2.push_back((double)array2[i]);
}
Mat firstArray = Mat(arr1);
Mat secondArray = Mat(arr2);
std::cout<<"Type control: "<<firstArray.type()<<std::endl;
createHanningWindow(hann, firstArray.size(), CV_64F);
Point2d shift = phaseCorrelate(firstArray, secondArray,hann);
std::cout<<"shift: "<<shift.x<<";"<<shift.y<<std::endl;
}
What am I doing wrong?
I have actually implemented this method for OpenCV, but unfortunately it is only in the SVN trunk at this stage.
Here is a sample using the new method.
If you would like to reference my implementation of it, you can find that here.
Also, here is the test case for an additional example of using it.
If you would like to use the trunk you can get a hold of it doing this:
Here is the CMake build guide for Linux. Here is the build guide for Windows.
EDIT :
Got a patch for you 🙂
I found a few bugs in my code as well, so they should be corrected now. It also should support 1D phase-correlation now. I also found an issue with the
cv::sqrt()function causing some -nan’s to show up even thoughstd::sqrt()did not. I’m guessing it’s either a bug with OpenCV, or just an accuracy issue. Haven’t dug into it enough to find out though.Unfortunately, you can’t just use
svn updateto get my latest changes because I have to wait for the OpenCV developers to apply this patch. So, instead of you having to wait on that here is a patch you can apply to the$(OPENCV_SRC)/modules/imgproc/src/phasecorr.cppfile. Save this file as something likephasecorr.patch, and place it in the root of the OpenCV source directory. Here is a short TortoiseSVN guide for creating/applying patches from/to source trees.Finally, here is a code sample of using the 1D phase correlation I was using.
You should see an output of (-2, 0.5). The
yvalue will always be 0.5 in the 1D case because that would be midway through the only row.Hope that is helpful to you!