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

0

У меня проблемы с функцией 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;
}

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

Теги:
opencv
dft

2 ответа

0

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

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

data[i] type is 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

imgReal - по умолчанию не заполняется нулями.

  • 0
    спасибо, я уже исправил это, и он изменил значение result [0], так что sqrt (result [0]) / 1024 имеет значение 127, что имеет смысл, но проблема на самом деле в функции MakeDFT.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню