我正在尝试使用基于matlab /倍频程代码的openCv计算希尔伯特变换
function y = hilbert(x)
if nargin != 1, usage("y = hilbert(x)"); endif
if !isreal(x), error("hilbert: requires real input vector"); endif
transpose = rows(x)==1;
if transpose, x=x.'; endif
[r, c] = size(x);
n=2^nextpow2(r);
if r < n, x = [ x ; zeros(n-r, c) ]; endif
y = fft(x);
y = ifft([y(1,:) ; 2*y(2:n/2,:) ; y(n/2+1,:) ; zeros(n/2-1,columns(y))]);
if r < n, y(r+1:n,:) = []; endif
if transpose, y = y.'; endif
endfunction
和我的c ++代码
#include <opencv2/core.hpp>
#include <opencv2/core/eigen.hpp>
#include "Eigen/Dense"
class HilbertTransformTest{
private:
cv::Mat CreateFilter(cv::Mat &data)const {
cv::Mat factor = cv::Mat::ones( data.rows, data.cols, CV_32FC2 );
for (int i=0; i<data.rows; ++i){
for (int j=1; j<data.cols/2; ++j){
factor.at<cv::Vec2f>(i, j)[0] = 2;
factor.at<cv::Vec2f>(i, j)[1] = 2;
factor.at<cv::Vec2f>(i, data.cols-j)[0] = 0;
factor.at<cv::Vec2f>(i, data.cols-j)[1] = 0;
}
}
return factor;
}
cv::Mat GetComplexMat(cv::Mat &Data) const {
cv::Mat planes[] = {cv::Mat_<float>(Data), cv::Mat::zeros(Data.size(), CV_32F)};
cv::Mat complexI;
cv::merge(planes, 2, complexI);
return complexI;
}
cv::Mat GenerateData() const {
Eigen::Matrix<float, -1, -1, Eigen::RowMajor> Data(1, 256);
cv::Mat Vis;
for (int iter = 0; iter < Data.cols(); ++iter) {
double t = double(iter) / 255.0 * 10.0;
Data(0, iter) = std::sin(2 * CV_PI * 0.5 * t);
}
cv::eigen2cv(Data, Vis);
return Vis;
}
public:
HilbertTransformTest() {
cv::Mat Data = GenerateData();
cv::Mat Kernel = CreateFilter(Data);
cv::Mat ComplexData = GetComplexMat(Data);
cv::Mat rfSpectrum;
cv::dft(ComplexData, rfSpectrum, cv::DFT_COMPLEX_OUTPUT);
cv::multiply(rfSpectrum, Kernel, rfSpectrum, 1.0, CV_32FC2);
cv::idft(rfSpectrum, ComplexData, cv::DFT_ROWS + cv::DFT_COMPLEX_OUTPUT + cv::DFT_SCALE);
cv::Mat planes[2];
cv::split(ComplexData, planes);
cv::Mat REAL = planes[0];
cv::Mat IMAG = cv::abs(planes[1]);
}
};
在iftf之后,我应获得Pi / 2信号(IMAG)的偏移并以REAL形式复制信号,但虚部为绝对值。我检查了matalb代码,直到ifft为止一切都是一样的,并且返回了(在八度音阶中)很好的虚部,但是openCV ifft仅创建了正值。