【화상 처리 100개 노크에 도전】Q.32. 푸리에 변환

10433 단어 C++이미지 처리

사용한 라이브러리



【화상 처리 100개 노크】 독자적인 화상 입출력 클래스를 만든다
【화상 처리 100개 노크에 도전】독자적인 이산 푸리에 변환 클래스를 만든다

Q.32. 푸리에 변환



2차원 이산 푸리에 변환(DFT)을 구현하고 imori.jpg를 그레이스케일화했지만 주파수의 파워 스펙트럼을 표시하라. 또한 역이차원 이산 푸리에 변환(IDFT)으로 이미지를 복원하라.

이미지의 파워 스펙트럼은 직류 부근의 값이 크기 때문에 원점 부근만 새하얗게 되어 전체 분포를 잘 모르는 경우가 많습니다. 이 때문에 종종 로그가 표시됩니다. 이번에는 수치 데이터로 출력하여 Gnuplot으로 log 표시합니다.
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);
    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < height; j++)
        {
            std::cout << i << " " << j << " " << std::abs(F[i][j]) << std::endl;
        }
        std::cout << std::endl;
    }

    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;
}
gnuplot> set log z
gnuplot> splot "fourier.txt" using 1:2:3 with pm3d



미묘···.

좋은 웹페이지 즐겨찾기