使用したライブラリ
【画像処理100本ノック】独自の画像入出力クラスを作る
【画像処理100本ノックに挑戦】独自の離散フーリエ変換クラスを作る
Q.33. フーリエ変換 ローパスフィルタ
imori.jpgをグレースケール化したものをDFTし、ローパスフィルタを通してIDFTで画像を復元せよ。
DFTシフトして高周波を落とし、DFT逆シフトし、逆フーリエ変換すればOKです。
int main()
{
PPM ppm("imori.pnm");
int width = ppm.Get_width();
int height = ppm.Get_height();
std::vector<std::vector<std::complex<double>>> f(width, std::vector<std::complex<double>>(height));
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
int r = ppm(i, j, 'r');
int g = ppm(i, j, 'g');
int b = ppm(i, j, 'b');
int y = (std::round)(0.2126 * r + 0.7152 * g + 0.0722 * b);
f[i][j] = y;
}
DFT2D dft2d(width, height);
auto F = dft2d.forward(f);
F = dft2d.shift(F);
double r = width / 2;
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
if ((i - width / 2) * (i - width / 2) + (j - height / 2) * (j - height / 2) > 0.25 * r * r) F[i][j] = 0;
}
F = dft2d.ishift(F);
f = dft2d.backward(F);
PPM ppm2(width, height);
for (int j = 0; j < height; j++)
for (int i = 0; i < width; i++)
{
int val = f[i][j].real();
if (val >= 256) val = 255;
if (val < 0)val = 0;
ppm2(i, j, 'r') = val;
ppm2(i, j, 'g') = val;
ppm2(i, j, 'b') = val;
}
ppm2.Flush("out.ppm");
return 0;
}