Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
0 / 0 / 0
Регистрация: 13.08.2021
Сообщений: 19
1
Delphi 6-7

Ускорить программу, которая выполняет преобразование Фурье

13.08.2021, 18:52. Показов 1950. Ответов 27

Author24 — интернет-сервис помощи студентам
Здравствуйте. Столкнулся с проблемой, программа медленно работает. Подключить модули, которые выполняют быстрое преобразование Фурье (FFT) не получается. В общем, нужна помощь с ускорением работы программы.
Преобразование Фурье над двумерным массивом из изображения. Важно, изображение должно быть формата JPEG с глубиной цвета 8-bit
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
procedure TForm1.Button2Click(Sender: TObject);
var
q,s,i,j           : integer;
v,u,x,y,f           : integer;
g                 : boolean;
scan              : pByteArray;
img               : Timage;
md                : real;
re,im             : real;
Pixel             : TColor;
begin
 
  M := bmp1.Height;
  N := bmp1.Width;
 
    begin
    for v := 0 to M - 1 do begin
       for u := 0 to N - 1 do begin
          md := 0;  Re := 0;  Im := 0;
          irmage[v,u].Re := 0;
          irmage[v,u].Im := 0;
          for y := 0 to M - 1 do begin
            scan := bmp1.ScanLine[y];
            for x := 0 to N - 1 do begin
              f:= 0;
              f := round(scan[x]);
              if odd(x+y) then f := f*(-1);
              Re := Re + cos((-1)*2*pi*(u*x/M+v*y/N))*f;
              Im := Im + sin((-1)*2*pi*(u*x/M+v*y/N))*f;
            end;
          end;
          irmage[v,u].Re := Re/(M*N);
          irmage[v,u].Im := Im/(M*N);
          irmage2[v,u].Re := Re/(M*N);
          irmage2[v,u].Im := Im/(M*N);
          md := sqrt( Re*Re/m*n + Im*Im/m*n );
          irmage[v,u].Modul := md;
          i := round (20 * ln(1+md));
          if i >= 255 then i := 255;
          bmp2.Canvas.Pixels[u,v] := rgb( i, i, i );
       end;
    end;
    image2.Picture.Bitmap.Assign(bmp2);
    bmp1.Free;
    bmp2.Free;
    end;
end;
Обратное преобразование Фурье
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
procedure TForm1.Button3Click(Sender: TObject);
var
  i,j,y,x,u,v :integer;
  re,im,md    :real;
  f           :integer;
begin
     bmp1:=TBitmap.Create;
     bmp2:=TBitmap.Create;
     Jpg := TJPEGImage.Create;
     Jpg.LoadFromFile(opendialog1.FileName);
     Bmp2.Assign(Jpg);
    for y:=0 to M - 1 do  begin
      for x:=0 to N - 1 do  begin
         md := 0;  Re := 0;  Im := 0; f := 1;
         for V:=0 to M - 1 do begin
           for U:=0 to N - 1 do begin
             Re := Re + irmage2[v,u].Re * COS(2*pi*(u*x/M+v*y/N)) - irmage2[v,u].Im * SIN(2*pi*(u*x/M+v*y/N));
             Im := Im + irmage2[v,u].Im * COS(2*pi*(u*x/M+v*y/N)) + irmage2[v,u].Re * SIN(2*pi*(u*x/M+v*y/N));
              end;
          end;
          if odd(x+y) then f := f*(-1);
          md := sqrt(Re*Re + Im*Im);
          i := round(re*f);
          bmp2.Canvas.Pixels[x,y] := rgb(i,i,i);
      end;
    end;
    image3.Picture.Bitmap.Assign(bmp2);
end;
end.
Так же прикреплю архив с программой.
Вложения
Тип файла: rar Фурье.rar (216.2 Кб, 10 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
13.08.2021, 18:52
Ответы с готовыми решениями:

Составьте программу, которая выполняет чертёж
Составьте программу, которая выполняет чертёж одной из деталей и высчитывает ещё площадь. Масштаб:...

Составьте программу, которая выполняет чертёж
Составьте программу, которая выполняет чертёж одной из деталей и высчитывает ещё площадь. Масштаб:...

Найти коэффиценты разложения в ряд Фурье, используя быстрое преобразование Фурье (БПФ)
Прошу помочь мне в нелеггкой задачке нужно для заданной на периоде 2∏ функции f(x) найти...

Обратное дискретное преобразование Фурье без использования быстрого преобразования Фурье (функции ifft)
Здравствуйте! Возникла необходимость получить правильно обратное дискретное преобразование Фурье,...

27
Модератор
3751 / 2251 / 782
Регистрация: 15.11.2015
Сообщений: 8,964
17.08.2021, 11:00 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Fourier Посмотреть сообщение
но я не могу сделать [M,N] локальными т.к. при выполнении другого блока он просто скопирует первое изображение в третье.
Очень плохая идея надеяться на инициализацию M и N в другой процедуре, потом загружать изображение и ожидать, что размеры изображения совпадут с заданными заранее. Что мешает и тут сделать
Delphi
1
2
  M := bmp2.Height;
  N := bmp2.Width;
?

Добавлено через 6 минут
Зачем тут загружать изображение из файла
Delphi
1
2
     Jpg.LoadFromFile(opendialog1.FileName);
     Bmp2.Assign(Jpg);
если далее оно не используется, а просто переписывается?

Добавлено через 6 минут
Поздравляю, оно работает. Но для неквадратного изображения что-то не так, возможно, координаты где-то перепутаны.
0
0 / 0 / 0
Регистрация: 13.08.2021
Сообщений: 19
17.08.2021, 11:17  [ТС] 22
AzAtom,
Цитата Сообщение от AzAtom Посмотреть сообщение
Очень плохая идея надеяться на инициализацию M и N в другой процедуре, потом загружать изображение и ожидать, что размеры изображения совпадут с заданными заранее. Что мешает и тут сделать

M := bmp2.Height;
N := bmp2.Width;

?
Я подумал и понял, что ничего не мешает, я так и сделал.
Цитата Сообщение от AzAtom Посмотреть сообщение
Зачем тут загружать изображение из файла
Delphi

Jpg.LoadFromFile(opendialog1.FileName);
Bmp2.Assign(Jpg);

если далее оно не используется, а просто переписывается?
Это так, не нужная часть кода. Просто я ещё пытаюсь со всем этим разобраться и понять как работает. Так что там встречается много не нужного. Но не думаю, что это существенно замедляет программу.
Программу сильно замедляет обработка изображений. При использовании изображения 100x100 время выполнения: примерно 20 сек. при прямом преобразовании и 36 сек. при обратном. Это печально
0
Модератор
3751 / 2251 / 782
Регистрация: 15.11.2015
Сообщений: 8,964
17.08.2021, 11:27 23
Fourier, вот это выражение:
Delphi
1
2
          Re := Re + cos((-1)*2*pi*(u*x/M+v*y/N))*f;
          Im := Im + sin((-1)*2*pi*(u*x/M+v*y/N))*f;
Для каждого пикселя N*M раз заново считаются выражения cos((-1)*2*pi*(u*x/M+v*y/N)) и sin((-1)*2*pi*(u*x/M+v*y/N)), но они для каждого пикселя одинаковы. Почему бы их не посчитать 1 раз и не занести в массив и уже значение из массива умножать на f?

Добавлено через 4 минуты
А, не, ошибся, там ещё вложенные циклы.
0
0 / 0 / 0
Регистрация: 13.08.2021
Сообщений: 19
17.08.2021, 11:46  [ТС] 24
AzAtom, ага. Была идея как-то заменить это "sincos", которая в модуле MATH, но не получилось
0
Модератор
3751 / 2251 / 782
Регистрация: 15.11.2015
Сообщений: 8,964
17.08.2021, 11:58 25
Цитата Сообщение от Fourier Посмотреть сообщение
Была идея как-то заменить это "sincos"
Кстати, отличная идея. Аргументы одинаковые, а команда процессора именно sincos и сразу вычисляет обе функции.

Добавлено через 8 минут
На картинке 100х100 с отдельными Sin, Cos у меня получилось 12,6 сек и с SinCos получилось 8,4 сек прямое преобразование.
0
0 / 0 / 0
Регистрация: 13.08.2021
Сообщений: 19
17.08.2021, 12:04  [ТС] 26
AzAtom, Ваш компьютер явно лучше моего. 4,2 сек в выигрыше - это отлично. У вас получилось это реализовать ?
0
Модератор
3751 / 2251 / 782
Регистрация: 15.11.2015
Сообщений: 8,964
17.08.2021, 12:14 27
Fourier, ноутбучный Core i5 2 поколения, лет 9 ему.
Цитата Сообщение от Fourier Посмотреть сообщение
У вас получилось это реализовать ?
SinCos? Да:
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
uses ... Math;
...
procedure TForm1.Button2Click(Sender: TObject);
var
...
  s1, c1: extended;
begin
...
//          Re := Re + cos((-1)*2*pi*(u*x/M+v*y/N))*f; // Вместо этих строк
//          Im := Im + sin((-1)*2*pi*(u*x/M+v*y/N))*f;
          SinCos((-1)*2*pi*(u*x/M+v*y/N), s1, c1); // теперь вот эти строки
          Re := Re + c1*f;
          Im := Im + s1*f;
...
1
0 / 0 / 0
Регистрация: 13.08.2021
Сообщений: 19
17.08.2021, 12:35  [ТС] 28
AzAtom, Огромнейшее тебе спасибо!
Я теперь разобрался как работает "sincos" и теперь при использовании изображения 100х100 время выполнения примерно: 13 сек. при прямом и 12 сек. при обратном. Вот это я понимаю прирост скорость. Огромное спасибо
Увы идей по ускорению больше нет.
P.S.
И у меня старенький ноутбук на AMD A10-5750M
0
17.08.2021, 12:35
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
17.08.2021, 12:35
Помогаю со студенческими работами здесь

Написать программу, которая выполняет вычисления по формуле
х=(а*2+b*c+5)(a*d+3) вот что получилось: .model small .stack 100h .data a db ? b db ? c db ?...

Написать программу, которая выполняет следующие действия
Создать текстовый файл согласно данной записи AEROFLOT, содержащий следующие поля: 1 Название...

Разработать программу, которая выполняет следующие операции:
Разработать программу, которая выполняет следующие операции: -Удаление из списка первого вхождения...

Составить программу которая выполняет вызовы функций
Составить программу, которая выполняет вызовы функций с помощью указателей Первая функция - ...

Составить программу которая выполняет следующие действия
Составить программу которая выполняет следующие действия: 1. Создает динамический список 2....

JS - Напишите программу, которая выполняет следующие действия:
Здравствуйте, уважаемые! Никак не могу понять, где у меня ошибка... Напишите программу,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
28
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru