基本原理的实现其实和二维差不多,该文章链接为:http://blog.csdn.net/ebowtang/article/details/51287309
下图展示了该算法对指定偏移量的准确估计:
参考代码:
#include <iostream>
#include <fftw3.h>
#include <vector>
#include <math.h>
using namespace std;
/** \brief PhaseCorrelation1D compute the offset between two input vectors
* based on POMF (Phase Only Matched Filter)
* -->> Q(k) = conjugate(S(k))/|S(k)| * R(k)/|R(k)|
* -->> q(x) = ifft(Q(k))
* -->> (xs,ys) = argmax(q(x))
* Note that the storage order of FFTW is row-order, while the storage
* order of Eigen is DEFAULT column-order.
*/
void PhaseCorrelation1D(vector<double> &signal,
const vector<double> &pattern,
const int size,
int &offset)
{
// 错误
if (signal.size() != size ||
pattern.size() != size)
{
std::cout << "The size of vector input for PhaseCorrelation wrong!" << std::endl;
return;
}
fftw_complex *signal_vector = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*size);
fftw_complex *pattern_vector = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*size);
for (unsigned int i = 0; i < signal.size(); i++)
{
signal_vector[i][0] = *(signal.data() + i);
signal_vector[i][1] = 0;
pattern_vector[i][0] = *(pattern.data() + i);
pattern_vector[i][1] = 0;
}
// 傅里叶变换
fftw_plan signal_forward_plan = fftw_plan_dft_1d(size, signal_vector, signal_vector,
FFTW_FORWARD, FFTW_ESTIMATE);
fftw_plan pattern_forward_plan = fftw_plan_dft_1d(size, pattern_vector, pattern_vector,
FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(signal_forward_plan);
fftw_execute(pattern_forward_plan);
// 求取互功率谱
fftw_complex *cross_vector = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*size);
double temp;
for (int i = 0; i<size; i++)
{
cross_vector[i][0] = (pattern_vector[i][0] * signal_vector[i][0]) -
(pattern_vector[i][1] * (-signal_vector[i][1]));
cross_vector[i][1] = (pattern_vector[i][0] * (-signal_vector[i][1])) +
(pattern_vector[i][1] * signal_vector[i][0]);
temp = sqrt(cross_vector[i][0] * cross_vector[i][0] + cross_vector[i][1] * cross_vector[i][1]);
cross_vector[i][0] /= temp;
cross_vector[i][1] /= temp;
}
// 傅里叶反变换
// FFTW computes an unnormalized transform,
// in that there is no coefficient in front of
// the summation in the DFT.
// In other words, applying the forward and then
// the backward transform will multiply the input by n.
// BUT, we only care about the maximum of the inverse DFT,
// so we don't need to normalize the inverse result.
// the storage order in FFTW is row-order
fftw_plan cross_backward_plan = fftw_plan_dft_1d(size, cross_vector, cross_vector,
FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(cross_backward_plan);
// 释放资源
fftw_destroy_plan(signal_forward_plan);
fftw_destroy_plan(pattern_forward_plan);
fftw_free(signal_vector);
fftw_free(pattern_vector);
vector<double> cross_real(size,0.0);
for (int i = 0; i < size; i++)
cross_real[i] = cross_vector[i][0];
//求取偏移量
int max_loc = 0;
float unuse = 0.0;
double maxcoeff = INT_MIN;
for (unsigned int i = 0; i<cross_real.size(); i++)
{
if (maxcoeff < cross_real[i])
{
maxcoeff = cross_real[i];
max_loc = i;
unuse = cross_real[i];
}
}
offset = (int)max_loc;
if (offset > 0.5*size)
offset = offset - size;
}
void offsetArr(vector<double> &signal,vector<double> &pattern,int offset)
{
int nsize = signal.size();
for (int i = offset; i < nsize; i++)
pattern[i - offset] = signal[i];
for (int i = 0; i < offset; i++)
pattern[nsize-i-1] = signal[i];
}
int main()
{
int nsize = 32;
vector<double> signal(nsize, 0), pattern(nsize, 0);
for (int i = 0; i < nsize; i++)
signal[i] = rand() % nsize;
int myoffset = 10;
offsetArr(signal,pattern,myoffset);
int offset = 0;
PhaseCorrelation1D(signal,pattern,nsize,offset);
cout << "原信号(随机生成)为: "<< endl;
for (int i = 0; i < nsize; i++)
cout<<signal[i]<<" ";
cout << endl;
cout << "对原信号指定的偏移量为:" << myoffset << endl;
cout<< "偏移信号为: " << endl;
for (int i = 0; i < nsize; i++)
cout << pattern[i] << " ";
cout << endl;
cout <<"相位相关法求取的偏移量为:" <<offset << endl;
getchar();
return 0;
}
参考资源:
【1】MIT,FFTW库
【2】Joseph L. Horner and Peter D. Gianino. Phase-only matched ltering. Applied Optics, 23(6):812-816, 1984.
【3】中国科学技术大学信号统计处理研究院,郑志彬,叶中付,《基于相位相关的图像配准算法》,2006,12