- •Москва, 2001
- •Введение.
- •Используя спектральную функцию s(yk) , кусочно-гладкую функциюf(X) периодаl можно представить в виде
- •Инструкция пользователя:
- •Аппаратные и программные требования:
- •Текст программы: { Текст основной программы furie.Cpp}
- •7) Классы и методы , используемые в программе
- •8)Список литературы:
Используя спектральную функцию s(yk) , кусочно-гладкую функциюf(X) периодаl можно представить в виде



f(x)=
1/l S(yk)e2ПiykX
Преобразования Фурье играют большую роль в распознавании образов , в моделировании фильтров , при корректировке изображений и в целом ряде других задач.
Известно , что аналитическое вычисление интегралов (*) и (**) вызывает , как правило , большие трудности , поэтому представляют большой интерес методы численной реализации этих интегралов.В связи с этим был разработан метод дискретного преобразования фурье (ДПФ) . интенсивное использование которого началось после введения в технику вычислений так называемого алгоритма «быстрого преобразования фурье» (БПФ).Этот алгоритм для вычисления БПФ был предложен Кули и Таки в 1965 г., хотя в других вычислениях он применялся значительно раньше.
Под дискретным преобразованием фурье понимается пара преобразований , устанавливающих взаимосвязь между конечным числом дискретных выборок как временной функции f(t), так и её частотного спектра S(y) .В случае 2N равноудалённых выборок в точках
tk=
t0+k
t , k=0,1,2,...,2N-1 ,и
yk=
y0+n
t , n=0,1,2,...,2N-1
Эти преобразования записываются обычно в виде



S^(yn)
=
t f(tk)e-2Пiyntk





f(tk)
=
y s^(yn)e2Пiyntk
З
начения
частотного спектраS^(yn)
,
вообще говоря , отличны от значений
спектра S(yn)
.По
одному из свойств преобразований фурье
:
S^(y) = S1(y)S2(y-т)dт , где S1 и S2 – преобразования
фурье функций f1(t) и f2(t),т.е S^(y) является свёрткой.Это вызывает размыте по частоте спектральной функции, а также размытие по фазе.
Если спектр функции f(t) представляет непрерывную функцию S(y) , то её размывание происходит согласно формуле:




S^(y)=
t S(т)e-Пi(y-т)(2N-1)
t(sin2П(y-т)N
t)/(sinП(y-т)
t) dt
Э
то
означает , что замена бесконечного
интеграла конечной суммой с равномерными
выборками приводит к спектральной
функцииS^(y) ,
имеющей период 1/ t и
осуществляющей размывание по частоте
и изменение по фазе пиков исходной
спектральной функцииS(y).
Инструкция пользователя:
запустить компилятор CBuilder 4.0,
открыть файл проекта furie.bpr,
запустить программу на выполнение (F9)
нажать кнопку ЗНАЧЕНИЯ,
в появившемся диалоговом окне ввести коэффициенты полинома,
нажать кнопку ПЕРЕСЧИТАТЬ,
на экран будет выведен входной сигнал, амплитудный спектр и фазовый спектр,
для выхода из программы необходимо нажать кнопку ЗАКРЫТЬ.
Программа позволяет загружать результаты предыдущих вычи-слений без ввода значений коэффициентов полинома из файла
SPECTR.DAT (для этого нужно нажать кнопку ЗАГРУЗИТЬ) .В
этот файл автоматически записываются значения сигнала и
спектров при выходе из программы.
Аппаратные и программные требования:
Для запуска программы необходимо:
компьютер с процессором INTEL Pentium 100 и выше,
монитор, поддерживающий разрешение 800х600 точек,
1 Mb дискового пространства,
16 Mb оперативной памяти,
наличие операционной системы MS Windows 95 и выше,
наличие пакета Borland CBuilder версии 4.0
Необходимые файлы:
Текст программы: { Текст основной программы furie.Cpp}
#include <vcl.h>
#pragma hdrstop
USERES("furie.res");
USEFORM("mainunit.cpp", MainForm);
USEUNIT("data.cpp");
USEUNIT("_tdft.cpp");
USEFORM("Value.cpp", ValueForm);
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TMainForm), &MainForm);
Application->CreateForm(__classid(TValueForm), &ValueForm);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}
#include <vcl.h>
#pragma hdrstop
USERES("furie.res");
USEFORM("mainunit.cpp", MainForm);
USEUNIT("data.cpp");
USEUNIT("_tdft.cpp");
USEFORM("Value.cpp", ValueForm);
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TMainForm), &MainForm);
Application->CreateForm(__classid(TValueForm), &ValueForm);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}
{Текст модуля mainunit.cpp}
#include <vcl.h>
#pragma hdrstop
#include "mainunit.h"
#include "value.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "PERFGRAP"
#pragma link "CSPIN"
#pragma resource "*.dfm"
TMainForm *MainForm;
void __fastcall OutGraph()
{
// Отображение графиков
int pos = MainForm->ScrollBar->Position;
int div = MainForm->Spin->Value;
MainForm->Canvas->Brush->Color = clBtnFace;
MainForm->Canvas->Pen->Color = clBlack;
MainForm->Canvas->FillRect(NewRect);
Y[0]=90;Y[1]=230;Y[2]=300;
for (i=0;i<3;i++)
{
MainForm->Canvas->MoveTo(X0,Y[i]);
MainForm->Canvas->LineTo(X1,Y[i]);
MainForm->Canvas->LineTo(X1-10,Y[i]-2);
MainForm->Canvas->LineTo(X1-10,Y[i]+2);
MainForm->Canvas->LineTo(X1,Y[i]);
MainForm->Canvas->MoveTo(X0,Y[i]);
MainForm->Canvas->LineTo(X0,Y[i]-60);
MainForm->Canvas->LineTo(X0-2,Y[i]-50);
MainForm->Canvas->LineTo(X0+2,Y[i]-50);
MainForm->Canvas->LineTo(X0,Y[i]-60);
}
maximum = abs(x_R[0]);
for(n = 0 ;n < _N; n++)
{
if (maximum < abs(x_R[n])) {maximum = abs(x_R[n]);}
}
if (maximum != 0) {norm = 70/maximum;}
else {norm = 0;}
MainForm->Canvas->MoveTo(X0,-(int)(x_R[pos]*norm)+Y0);
for(n = pos ;n < (_N/div + pos); n++)
{
MainForm->Canvas->LineTo((n-pos)*(X1-X0)/(_N/div-1)+X0,-(int)(x_R[n]*norm)+Y0);
}
MainForm->Canvas->Pen->Color=clRed;
MainForm->Canvas->MoveTo(X0,Y1);
maximum = abs(m[0]);
for(n = 0 ;n < _N; n++)
{
if (maximum < abs(m[n])) {maximum = abs(m[n]);}
}
if (maximum != 0) {norm = 70/maximum;}
else {norm = 0;}
for(n = pos;n < _N/div + pos; n++)
{
MainForm->Canvas->MoveTo((n-pos)*(X1-X0)/(_N/div - 1)+X0,Y1);
MainForm->Canvas->LineTo((n-pos)*(X1-X0)/(_N/div - 1)+X0,-(int)(m[n]*norm)+Y1);
}
MainForm->Canvas->Pen->Color=clBlue;
MainForm->Canvas->MoveTo(X0,Y2);
for(n = pos;n < _N/div + pos; n++)
{
MainForm->Canvas->MoveTo((n-pos)*(X1-X0)/(_N/div - 1)+X0,Y2);
MainForm->Canvas->LineTo((n-pos)*(X1-X0)/(_N/div - 1)+X0,-(int)(f[n]*10)+Y2);
}
}
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::CloseButtonClick(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormCreate(TObject *Sender)
{
// Установка начальных параметров компонентов
Panel1->Left = (ClientWidth - Panel1->Width) / 2;
Panel1->Top = (ClientHeight - Panel1->Height) / 2;;
ScrollBar->Min = 0;
ScrollBar->Max = _N;
ScrollBar->Width = X1 - X0;
ScrollBar->Top = Y2 + 50;
ScrollBar->Left = X0;
ScrollBar->Visible = False;
Canvas->Brush->Color = clWhite;
Canvas->FillRect(NewRect);
ButtonPanel->Show();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::CalcButtonClick(TObject *Sender)
{
// Задание входного сигнала и вычисление преобразрвания Фурье
Panel1->Show();
int tmp;
Application->ProcessMessages();
for (n=0;n<_N;n++)
{
tmp = n%T;
x_R[n] = ValueForm->Spin1->Value
+ ValueForm->Spin2->Value * tmp
+ ValueForm->Spin3->Value * tmp * tmp
+ ValueForm->Spin4->Value * tmp * tmp * tmp
+ ValueForm->Spin5->Value * tmp * tmp * tmp * tmp;
x_I[n] = 0;
}
// Открытие файла на запись
if ((out = fopen("SPECTR.dat", "w")) == NULL)
{
Panel1->Hide();
ShowMessage("Ошибка создания файла...");
}
else
{
MyDFT.Forward(x_R,x_I,X_R,X_I);
MyDFT.Magnitude(m,X_R,X_I);
MyDFT.Phase(f,X_R,X_I);
Panel1->Hide();
for (n=0;n<_N;n++) // Пишем данные в файл
{
fprintf(out,"%lf\n%lf\n%lf\n",x_R[n],m[n],f[n]); //Сигнал,амплитудный спектр
} //и фазовый спектр
fclose(out);
}
OutGraph();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::DrawButtonClick(TObject *Sender)
{
if ((out = fopen("SPECTR.dat", "r")) == NULL)
{
Panel1->Hide();
ShowMessage("Ошибка чтения файла...");
}
else
{
for (n=0;n<_N;n++) // Пишем данные в файл
{
fscanf(out,"%lf\n%lf\n%lf\n",&x_R[n],&m[n],&f[n]);//Сигнал,амплитудныйспектр
} //и фазовый спектр
fclose(out);
}
OutGraph();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ScrollBarChange(TObject *Sender)
{
// Изменение значения ползунка
Label1->Caption = ScrollBar->Position; // Вывод значения ползунка
MainForm->Canvas->FillRect(NewRect); // Очистка формы
OutGraph(); // Вывод графиков
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SpinChange(TObject *Sender)
{
// Изменение коэффициента развёртки
if (Spin->Value > 1) {ScrollBar->Show();}
else {ScrollBar->Hide();}
ScrollBar->Max = _N - _N/Spin->Value;
OutGraph();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ParamButtonClick(TObject *Sender)
{
// Вывод окошка для ввода параметров А1,А2...
ValueForm->ShowModal();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormPaint(TObject *Sender)
{
// Перерисока формы при её перекрытии
OutGraph();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormShow(TObject *Sender)
{
// При отображении формы читаем из INI файла значения параметров полинома
TIniFile *INI = new TIniFile("dat.ini");
ValueForm->Spin1->Value = INI->ReadInteger("Parametrs","A1",1);
ValueForm->Spin2->Value = INI->ReadInteger("Parametrs","A2",2);
ValueForm->Spin3->Value = INI->ReadInteger("Parametrs","A3",3);
ValueForm->Spin4->Value = INI->ReadInteger("Parametrs","A4",4);
ValueForm->Spin5->Value = INI->ReadInteger("Parametrs","A5",5);
INI->~TIniFile();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::FormClose(TObject *Sender, TCloseAction &Action)
{
// При закрытии формы пишем в INI файл значения параметров полинома
TIniFile *INI = new TIniFile("dat.ini");
INI->WriteInteger("Parametrs","A1",ValueForm->Spin1->Value);
INI->WriteInteger("Parametrs","A2",ValueForm->Spin2->Value);
INI->WriteInteger("Parametrs","A3",ValueForm->Spin3->Value);
INI->WriteInteger("Parametrs","A4",ValueForm->Spin4->Value);
INI->WriteInteger("Parametrs","A5",ValueForm->Spin5->Value);
INI->~TIniFile();
}
{Текст модуля _tdft.cpp}
/*------------------------------------------------------------------------*/
/* */
/* TDFT.CPP - Complex Discrete Fourier Transform */
/* */
/* Copyright Eugene Emelin 2001 */
/* */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __MATH_H )
#include <math.h>
#endif // __MATH_H
#if !defined( __STDIO_H )
#include <stdio.h>
#endif // __STDIO_H
#if !defined( _pi)
#define _pi 3.1415926535897932384626
#endif // _pi
#if !defined( _2pi)
#define _2pi 6.283185307179586476925
#endif // _2pi
#if !defined( __PRECISION)
#define __PRECISION double
#endif // __PRECISION
#if !defined( _THRESHOLD)
#define _THRESHOLD 0.000001
#endif // _THRESHOLD
class TDFT
{
int N; // Number of Samples
int k; // Harmonic index
int n; // Sample index
public:
double Threshold; // Magnitude Threshold for Phase calculation in the case of very small magnitude
TDFT(int Length)
{
N = Length; Threshold = _THRESHOLD;
};
~TDFT(){};
private:
void Trans (__PRECISION *RI, __PRECISION *II, __PRECISION *RO, __PRECISION *IO, unsigned int k);
public:
void Forward (__PRECISION *RTime, __PRECISION *ITime, __PRECISION *RFreq, __PRECISION *IFreq);
void Inverse (__PRECISION *RFreq, __PRECISION *IFreq, __PRECISION *RTime, __PRECISION *ITime);
inline void Forward (__PRECISION *RTime, __PRECISION *ITime, __PRECISION *RFreq, __PRECISION *IFreq, unsigned int k);
inline void Inverse (__PRECISION *RFreq, __PRECISION *IFreq, __PRECISION *RTime, __PRECISION *ITime, unsigned int k);
void Magnitude (__PRECISION *Magn, __PRECISION *RFreq, __PRECISION *IFreq);
void Phase (__PRECISION *Phase, __PRECISION *RFreq, __PRECISION *IFreq);
};
void TDFT::Forward (__PRECISION *RTime, __PRECISION *ITime , __PRECISION *RFreq, __PRECISION *IFreq)
{
// Прямое преобразование Фурье
for(k = 0; k < N; k++)
{
Trans (RTime, ITime, RFreq, IFreq, k);
RFreq[k] /= N;
IFreq[k] /= -N;
}
};
void TDFT::Inverse (__PRECISION *RFreq, __PRECISION *IFreq, __PRECISION *RTime, __PRECISION *ITime)
{
// Обратное преобразование Фурье
for(k = 0; k < N; k++)
Trans (RFreq, IFreq, RTime, ITime, k);
};
inline void TDFT::Forward (__PRECISION *RTime, __PRECISION *ITime , __PRECISION *RFreq, __PRECISION *IFreq, unsigned int k)
{
// Прямое преобразование Фурье
// (перегруженная функция)
Trans (RTime, ITime, RFreq, IFreq, k);
RFreq[k] /= N;
IFreq[k] /= -N;
};
inline void TDFT::Inverse (__PRECISION *RFreq, __PRECISION *IFreq, __PRECISION *RTime, __PRECISION *ITime, unsigned int k)
{
// Обратное преобразование Фурье
// (перегруженная функция)
Trans (RFreq, IFreq, RTime, ITime, k);
};
void TDFT::Trans (__PRECISION *RI, __PRECISION *II, __PRECISION *RO, __PRECISION *IO, unsigned int k)
{
// Одна итерация преобразования Фурье
__PRECISION w, cosw, sinw;
RO[k] = 0;
IO[k] = 0;
for(n = 0; n < N; n++)
{
w = (__PRECISION)(_2pi*n*k)/N;
sinw = sin(w);
cosw = cos(w);
RO[k] += (RI[n]*cosw) - (II[n]*sinw);
IO[k] += (II[n]*cosw) + (RI[n]*sinw);
}
};
void TDFT::Magnitude(__PRECISION *Magn, __PRECISION *RFreq, __PRECISION *IFreq)
{
// Вычисление магнитуды
__PRECISION tmp;
for(k = 0; k <= N/2; k++)
{
tmp = (__PRECISION)sqrt( (RFreq[k]*RFreq[k]) + (IFreq[k]*IFreq[k]) );
Magn[k] = tmp;
Magn[N-k] = tmp;
}
};
void TDFT::Phase(__PRECISION *Phase, __PRECISION *RFreq, __PRECISION *IFreq)
{
// Вычисление фазы
for(k = 0; k < N; k++)
if (( fabs(RFreq[k]) < Threshold ) && ( fabs(IFreq[k]) < Threshold )) Phase[k] = 0;
else
{
if (RFreq[k] == 0) RFreq[k] = 1e-38;
Phase[k] = (__PRECISION) atan2(IFreq[k], RFreq[k]);
if (Phase[k] == -_pi) Phase[k] = _pi;
};
};
{Текст модуля VALUE.CPP}
#include <vcl.h>
#pragma hdrstop
#include "Value.h"
#include "Data.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CSPIN"
#pragma resource "*.dfm"
TValueForm *ValueForm;
//---------------------------------------------------------------------------
__fastcall TValueForm::TValueForm(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TValueForm::Button1Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TValueForm::Button2Click(TObject *Sender)
{
Close();
}
