-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
answer_33.cpp
180 lines (150 loc) · 4.6 KB
/
answer_33.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <math.h>
#include <complex>
const int height = 128, width = 128;
struct fourier_str {
std::complex<double> coef[height][width];
};
// RGB to Gray scale
cv::Mat BGR2GRAY(cv::Mat img){
// prepare output
cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);
// BGR -> Gray
for (int y = 0; y < height; y++){
for (int x = 0; x < width; x++){
out.at<uchar>(y, x) = (int)((float)img.at<cv::Vec3b>(y, x)[0] * 0.0722 + \
(float)img.at<cv::Vec3b>(y, x)[1] * 0.7152 + \
(float)img.at<cv::Vec3b>(y, x)[2] * 0.2126);
}
}
return out;
}
// Discrete Fourier transformation
fourier_str dft(cv::Mat img, fourier_str fourier_s){
double I;
double theta;
std::complex<double> val;
for ( int l = 0; l < height; l ++){
for ( int k = 0; k < width; k ++){
val.real(0);
val.imag(0);
for ( int y = 0; y < height; y ++){
for ( int x = 0; x < width; x ++){
I = (double)img.at<uchar>(y, x);
theta = -2 * M_PI * ((double)k * (double)x / (double)width + (double)l * (double)y / (double)height);
val += std::complex<double>(cos(theta), sin(theta)) * I;
}
}
val /= sqrt(height * width);
fourier_s.coef[l][k] = val;
}
}
return fourier_s;
}
// Inverse Discrete Fourier transformation
cv::Mat idft(cv::Mat out, fourier_str fourier_s){
double theta;
double g;
std::complex<double> G;
std::complex<double> val;
for ( int y = 0; y < height; y ++){
for ( int x = 0; x < width; x ++){
val.real(0);
val.imag(0);
for ( int l = 0; l < height; l ++){
for ( int k = 0; k < width; k ++){
G = fourier_s.coef[l][k];
theta = 2 * M_PI * ((double)k * (double)x / (double)width + (double)l * (double)y / (double)height);
val += std::complex<double>(cos(theta), sin(theta)) * G;
}
}
g = std::abs(val) / sqrt(height * width);
g = fmin(fmax(g, 0), 255);
out.at<uchar>(y, x) = (uchar)g;
}
}
return out;
}
// Low pass Filter
fourier_str lpf(fourier_str fourier_s, double pass_r){
// filtering
int r = height / 2;
int filter_d = (int)((double)r * pass_r);
for ( int j = 0; j < height / 2; j++){
for ( int i = 0; i < width / 2; i++){
if (sqrt(i * i + j * j) >= filter_d){
fourier_s.coef[j][i] = 0;
fourier_s.coef[j][width - i] = 0;
fourier_s.coef[height - i][i] = 0;
fourier_s.coef[height - i][width - i] = 0;
}
}
}
/*
fourier_str tmp_s;
// region change
for ( int j = 0; j < height / 2; j++){
for ( int i = 0; i < width / 2; i++){
// left top > right bottom
tmp_s.coef[height / 2 + j][width / 2 + i] = fourier_s.coef[j][i];
// right top > left bottom
tmp_s.coef[height / 2 + j][i] = fourier_s.coef[j][width / 2 + i];
// left bottom > right top
tmp_s.coef[j][width / 2 + i] = fourier_s.coef[height / 2 + j][i];
// right bottom > left top
tmp_s.coef[j][i] = fourier_s.coef[height / 2 + j][width / 2 + i];
}
}
// filtering
int r = height / 2;
int filter_d = (int)((double)r / 2);
for ( int j = 0; j < height / 2; j++){
for ( int i = 0; i < width / 2; i++){
if (sqrt(i * i + j + j) >= filter_d){
tmp_s.coef[height / 2 - j][width / 2 + i] = 0;
tmp_s.coef[height / 2 - j][width / 2 - i] = 0;
tmp_s.coef[height / 2 + i][width / 2 + i] = 0;
tmp_s.coef[height / 2 + i][width / 2 - i] = 0;
}
}
}
// return region
for ( int j = 0; j < height / 2; j++){
for ( int i = 0; i < width / 2; i++){
// left top > right bottom
fourier_s.coef[height / 2 + j][width / 2 + i] = tmp_s.coef[j][i];
// right top > left bottom
fourier_s.coef[height / 2 + j][i] = tmp_s.coef[j][width / 2 + i];
// left bottom > right top
fourier_s.coef[j][width / 2 + i] = tmp_s.coef[height / 2 + j][i];
// right bottom > left top
fourier_s.coef[j][i] = tmp_s.coef[height / 2 + j][width / 2 + i];
}
}
*/
return fourier_s;
}
// Main
int main(int argc, const char* argv[]){
// read original image
cv::Mat img = cv::imread("imori.jpg", cv::IMREAD_COLOR);
// Fourier coefficient
fourier_str fourier_s;
// output image
cv::Mat out = cv::Mat::zeros(height, width, CV_8UC1);
// BGR -> Gray
cv::Mat gray = BGR2GRAY(img);
// DFT
fourier_s = dft(gray, fourier_s);
// LPF
fourier_s = lpf(fourier_s, 0.5);
// IDFT
out = idft(out, fourier_s);
//cv::imwrite("out.jpg", out);
cv::imshow("answer", out);
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}