-
Notifications
You must be signed in to change notification settings - Fork 0
/
dft.cpp
94 lines (75 loc) · 2.89 KB
/
dft.cpp
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
void swapQuadrants(cv::Mat& image) {
cv::Mat tmp, A, B, C, D;
// se a imagem tiver tamanho impar, recorta a regiao para o maior
// tamanho par possivel (-2 = 1111...1110)
image = image(cv::Rect(0, 0, image.cols & -2, image.rows & -2));
int centerX = image.cols / 2;
int centerY = image.rows / 2;
// rearranja os quadrantes da transformada de Fourier de forma que
// a origem fique no centro da imagem
// A B -> D C
// C D B A
A = image(cv::Rect(0, 0, centerX, centerY));
B = image(cv::Rect(centerX, 0, centerX, centerY));
C = image(cv::Rect(0, centerY, centerX, centerY));
D = image(cv::Rect(centerX, centerY, centerX, centerY));
// swap quadrants (Top-Left with Bottom-Right)
A.copyTo(tmp);
D.copyTo(A);
tmp.copyTo(D);
// swap quadrant (Top-Right with Bottom-Left)
C.copyTo(tmp);
B.copyTo(C);
tmp.copyTo(B);
}
int main(int argc, char** argv) {
cv::Mat image, padded, complexImage;
std::vector<cv::Mat> planos;
image = imread(argv[1], cv::IMREAD_GRAYSCALE);
if (image.empty()) {
std::cout << "Erro abrindo imagem" << argv[1] << std::endl;
return EXIT_FAILURE;
}
// expande a imagem de entrada para o melhor tamanho no qual a DFT pode ser
// executada, preenchendo com zeros a lateral inferior direita.
int dft_M = cv::getOptimalDFTSize(image.rows);
int dft_N = cv::getOptimalDFTSize(image.cols);
cv::copyMakeBorder(image, padded, 0, dft_M - image.rows, 0,
dft_N - image.cols, cv::BORDER_CONSTANT,
cv::Scalar::all(0));
// prepara a matriz complexa para ser preenchida
// primeiro a parte real, contendo a imagem de entrada
planos.push_back(cv::Mat_<float>(padded));
// depois a parte imaginaria com valores nulos
planos.push_back(cv::Mat::zeros(padded.size(), CV_32F));
// combina os planos em uma unica estrutura de dados complexa
cv::merge(planos, complexImage);
// calcula a DFT
cv::dft(complexImage, complexImage);
swapQuadrants(complexImage);
// planos[0] : Re(DFT(image)
// planos[1] : Im(DFT(image)
cv::split(complexImage, planos);
// calcula o espectro de magnitude e de fase (em radianos)
cv::Mat magn, fase;
cv::cartToPolar(planos[0], planos[1], magn, fase, false);
cv::normalize(fase, fase, 0, 1, cv::NORM_MINMAX);
// caso deseje apenas o espectro de magnitude da DFT, use:
cv::magnitude(planos[0], planos[1], magn);
// some uma constante para evitar log(0)
// log(1 + sqrt(Re(DFT(image))^2 + Im(DFT(image))^2))
magn += cv::Scalar::all(1);
// calcula o logaritmo da magnitude para exibir
// com compressao de faixa dinamica
cv::log(magn, magn);
cv::normalize(magn, magn, 0, 1, cv::NORM_MINMAX);
// exibe as imagens processadas
cv::imshow("Imagem", image);
cv::imshow("Espectro de magnitude", magn);
cv::imshow("Espectro de fase", fase);
cv::waitKey();
return EXIT_SUCCESS;
}