

スケーリングはパワースペクトルの平方根の対数を取ったのですが、ImageJなどのプログラムで二次元FFTした結果と見比べると何かが違う気がします。どこかコードに間違えているところがあるのでしょうか？  
ちなみにFFT用のライブラリは、[「大浦版FFTのJava移植」](http://hp.vector.co.jp/authors/VA046927/fft4gjava.html)を使用しています。

例：  
元画像(lena)→[![lena](https://i.stack.imgur.com/fxXR6.png)](https://i.stack.imgur.com/fxXR6.png)  
このプログラムで処理した結果→[![FFT_1](https://i.stack.imgur.com/69BLK.png)](https://i.stack.imgur.com/69BLK.png)  
ImageJ→[![FFT_2](https://i.stack.imgur.com/vJKhU.png)](https://i.stack.imgur.com/vJKhU.png)

[code]

    import java.awt.image.BufferedImage;
    import java.io.File;
    import javax.imageio.ImageIO;
    
    public class show_resolution{
        public static void main(String args[]){
            if(args.length < 1) return;
            try{
                BufferedImage image = ImageIO.read(new File(args[0]));
                int w = image.getWidth(), h = image.getHeight();
                double[] image_data = new double[w * h * 2];
                // データを配列に代入する
                for(int y = 0; y < h; ++y){
                    for(int x = 0; x < w; ++x){
                        int color = image.getRGB(x, y);
                        int r = (color & 0xff0000) >> 16;
                        int g = (color & 0xff00) >> 8;
                        int b = color & 0xff;
                        image_data[(x + y * w) * 2] = 0.299 * r + 0.587 * g + 0.114 * b;
                        image_data[(x + y * w) * 2 + 1] = 0.0;
                    }
                }
                // 二次元FFT
                fft2d(image_data, w, h);
                // パワースペクトルに変換
                power_spectral(image_data, w, h);
                // 象限入れ替え
                swap_quadrants(image_data, w, h);
                // 正規化
                normalization(image_data, w, h);
                // 出力
                for(int y = 0; y < h; ++y){
                    for(int x = 0; x < w; ++x){
                        int Y = (int)(image_data[(x + y * w)] * 255);
                        if(Y > 255) Y = 255;
                        if(Y < 0) Y = 0;
                        image.setRGB(x, y, 0x010101 * Y + 0xff000000);
                    }
                }
                String file_name = args[0].substring(0, args[0].lastIndexOf(".")) + "_FFT.png";
                ImageIO.write(image, "png", new File(file_name));
            }catch(Exception error){
                error.printStackTrace();
            }
        }
        // 正規化
        static void normalization(double[] a, int w, int h){
            double min = a[0], max = a[0];
            for(int k = 1; k < w * h; ++k){
                min = Math.min(min, a[k]);
                max = Math.max(max, a[k]);
            }
            double diff = max - min;
            for(int k = 0; k < w * h; ++k){
                a[k] = (a[k] - min) / diff;
            }
        }
        // 象限入れ替え
        static void swap_quadrants(double[] a, int w, int h){
            int hw = w / 2, hh = h / 2;
            double[] b = new double[w * h];
            for(int y = 0; y < hh; ++y){
                for(int x = 0; x < hw; ++x){
                    b[(y + hh) * w + x] = a[y * w + (x + hw)];  //第1象限
                    b[(y + hh) * w + (x + hw)] = a[y * w + x];  //第2象限
                    b[y * w + (x + hw)] = a[(y + hh) * w + x];  //第3象限
                    b[y * w + x] = a[(y + hh) * w + (x + hw)];  //第4象限
                }
            }
            for(int k = 0; k < w * h; ++k){
                a[k] = b[k];
            }
        }
        // パワースペクトルに変換
        static void power_spectral(double[] a, int w, int h){
            for(int y = 0; y < h; ++y){
                for(int x = 0; x < w; ++x){
                    double re = a[(x + y * w) * 2];
                    double im = a[(x + y * w) * 2 + 1];
                    double norm = re * re + im * im;
                    if(norm != 0.0) norm = Math.log(norm) / 2;
                    a[x + y * w] = norm;
                }
            }
        }
        // 2次元FFT
        static void fft2d(double[] a, int w, int h){
            double[] b = new double[w * h * 2];
            // 水平方向のFFT
            for(int y = 0; y < h; ++y){
                fft1d(a, w * 2, y * w * 2);
            }
            // 転置操作
            transpose(a, b, w, h);
            // 垂直方向のFFT
            for(int x = 0; x < w; ++x){
                fft1d(b, h * 2, x * h * 2);
            }
            // 転置操作
            transpose(b, a, h, w);
        }
        // 1次元FFT
        static void fft1d(double[] a, int n, int p){
            double[] temp = new double[n];
            for(int k = 0; k < n; ++k){
                temp[k] = a[p + k];
            }
            FFT4g fft = new FFT4g(n);
            fft.rdft(1, temp);
            temp[1] = 0;
            for(int k = 0; k < n; ++k){
                a[p + k] = temp[k];
            }
        }
        // 行列の転置
        static void transpose(double[] src, double[] dst, int w, int h){
            for(int y = 0; y < h; ++y){
                for(int x = 0; x < w; ++x){
                    int p = x + y * w;
                    int q = y + x * h;
                    dst[q * 2    ] = src[p * 2];
                    dst[q * 2 + 1] = src[p * 2 + 1];
                }
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2015-10-31T14:52:04.487
18279
2015-10-31T14:52:04.487
12939
question
java
画像を2次元FFTで処理したいのですが、結果が正しくない気がします……