Разные результаты с cvDFT и DFT в OpenCV 2.4.8

У меня проблемы с функцией DFT в OpenCV 2.4.8 для c ++.

Я использовал изображение 10-фазной синусоидальной кривой, чтобы сравнить старый cvDFT () с более новой функцией C ++ DFT () (по одному измерению DFT по строкам).

Старая версия дает мне логичные результаты: очень высокий пик в пикселях 0 и 10, остальные почти 0.

Новая версия дает мне странные результаты с пиками по всему спектру.

Вот мой код:

#include "stdafx.h"
#include <opencv2\core\core_c.h>
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc_c.h>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\highgui\highgui_c.h>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\legacy\compat.hpp>

using namespace cv;void OldMakeDFT(Mat original, double* result)
{
const int width = original.cols;
const int height = 1;

IplImage* fftBlock = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1);

IplImage* imgReal = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 1);
IplImage* imgImag = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 1);
IplImage* imgDFT = cvCreateImage(cvSize(width, height), IPL_DEPTH_32F, 2);

Rect roi(0, 0, width, 1);
Mat image_roi = original(roi);
fftBlock->imageData = (char*)image_roi.data;

//cvSaveImage("C:/fftBlock1.png", fftBlock);

cvConvert(fftBlock, imgReal);

cvMerge(imgReal, imgImag, NULL, NULL, imgDFT);
cvDFT(imgDFT, imgDFT, (CV_DXT_FORWARD | CV_DXT_ROWS));

cvSplit(imgDFT, imgReal, imgImag, NULL, NULL);double re,imag;
for (int i = 0; i < width; i++)
{
re = ((float*)imgReal->imageData)[i];
imag = ((float*)imgImag->imageData)[i];
result[i] = re * re + imag * imag;

}

cvReleaseImage(&imgReal);
cvReleaseImage(&imgImag);
cvReleaseImage(&imgDFT);
cvReleaseImage(&fftBlock);
}

void MakeDFT(Mat original, double* result)
{
const int width = original.cols;
const int height = 1;
Mat fftBlock(1,width, CV_8UC1);

Rect roi(0, 0, width, height);
Mat image_roi = original(roi);
image_roi.copyTo(fftBlock);

//imwrite("C:/fftBlock2.png", fftBlock);

Mat planes[] = {Mat_<float>(fftBlock), Mat::zeros(fftBlock.size(), CV_32F)};
Mat complexI;

merge(planes, 2, complexI);
dft(complexI, complexI, DFT_ROWS); //also tried with DFT_COMPLEX_OUTPUT | DFT_ROWS
split(complexI, planes);

double re, imag;
for (int i = 0; i < width; i++)
{
re = (float)planes[0].data[i];
imag = (float)planes[1].data[i];
result[i] = re * re + imag * imag;
}
}bool SinusFFTTest()
{
const int size = 1024;
Mat sinTest(size,size,CV_8UC1, Scalar(0));
const int n_sin_curves = 10;
double deg_step = (double)n_sin_curves*360/size;
for (int j = 0; j < size; j++)
{
for (int i = 0; i <size; i++)
{
sinTest.data[j*size+i] = 127.5 * sin(i*deg_step*CV_PI/180) + 127.5;
}
}

double* result1 = new double[size];
double* result2 = new double[size];
OldMakeDFT(sinTest,result1);
MakeDFT(sinTest,result2);
bool identical = true;
for (int i = 0; i < size; i++)
{
if (abs(result1[i] - result2[i]) > 1000)
{
identical = false;
break;
}
}
delete[] result1;
delete[] result2;
return identical;
}

int _tmain(int argc, _TCHAR* argv[])
{
if (SinusFFTTest())
{
printf("identical");
}
else
{
printf("different");
}
getchar();
return 0;
}

Может ли кто-нибудь объяснить разницу?

0

Решение

imgReal — по умолчанию не заполнено нулями.

0

Другие решения

Ошибка в MakeDFT() функция:

  re = (float)planes[0].data[i];
imag = (float)planes[1].data[i];

data[i]Тип — это uchar, и его преобразование в float не является правильным.

Исправление:

re = planes[0].at<float>(0,i);
imag = planes[1].at<float>(0,i);

После этого изменения старая и новая версии DFT дают одинаковые результаты. Или вы можете использовать cv::magnitude() вместо вычисления суммы квадратов re а также imag:

Mat magn;
magnitude(planes[0], planes[1], magn);
for (int i = 0; i < width; i++)
result[i] = pow(magn.at<float>(0,i),2);

Это также дает тот же результат, что и старый cvDFT.

0

По вопросам рекламы [email protected]