使用jTransforms的png的DCT2

时间:2012-05-29 11:00:34

标签: java transform dct

我要做的是在Java中计算图像的2D DCT,然后将结果保存回文件。

读取文件:

coverImage = readImg(coverPath);
private BufferedImage readImg(String path) {

        BufferedImage destination = null;

        try {

            destination = ImageIO.read(new File(path));

        } catch (IOException e) {

            e.printStackTrace();

        }

        return destination;

    }

转换为float数组:

cover = convertToFloatArray(coverImage);
private float[] convertToFloatArray(BufferedImage source) {

        securedImage = (WritableRaster) source.getData();

        float[] floatArray = new float[source.getHeight() * source.getWidth()];
        floatArray = securedImage.getPixels(0, 0, source.getWidth(), source.getHeight(), floatArray);

        return floatArray;

    }

运行DCT:

runDCT(cover, coverImage.getHeight(), coverImage.getWidth());
private void runDCT(float[] floatArray, int rows, int cols) {

        dct = new FloatDCT_2D(rows, cols);

        dct.forward(floatArray, false);

        securedImage.setPixels(0, 0, cols, rows, floatArray); 

    }

然后将其保存为图像:

convertDctToImage(securedImage, coverImage.getHeight(), coverImage.getWidth());
private void convertDctToImage(WritableRaster secured, int rows, int cols) {

        coverImage.setData(secured);

        File file = new File(securedPath);
        try {
            ImageIO.write(coverImage, "png", file);
        } catch (IOException ex) {
            Logger.getLogger(DCT2D.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

但我得到的是:http://kyle.pl/up/2012/05/29/dct_stack.png

谁能告诉我我做错了什么?或许我在这里不明白?

1 个答案:

答案 0 :(得分:0)

这是一段代码,对我有用:

//reading image
BufferedImage image = javax.imageio.ImageIO.read(new File(filename));

//width * 2, because DoubleFFT_2D needs 2x more space - for Real and Imaginary parts of complex numbers
double[][] brightness = new double[img.getHeight()][img.getWidth() * 2];

//convert colored image to grayscale (brightness of each pixel)
for ( int y = 0; y < image.getHeight(); y++ ) {
    raster.getDataElements( 0, y, image.getWidth(), 1, dataElements );
    for ( int x = 0; x < image.getWidth(); x++ ) {
        //notice x and y swapped - it's JTransforms format of arrays
        brightness[y][x] = brightnessRGB(dataElements[x]);
    }
}

//do FT (not FFT, because FFT is only* for images with width and height being 2**N)
//DoubleFFT_2D writes data to the same array - to brightness
new DoubleFFT_2D(img.getHeight(), img.getWidth()).realForwardFull(brightness);

//visualising frequency domain
BufferedImage fd = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB);
outRaster = fd.getRaster();
for ( int y = 0; y < img.getHeight(); y++ ) {
    for ( int x = 0; x < img.getWidth(); x++ ) {
        //we calculate complex number vector length (sqrt(Re**2 + Im**2)). But these lengths are to big to
        //fit in 0 - 255 scale of colors. So I divide it on 223. Instead of "223", you may want to choose
        //another factor, wich would make you frequency domain look best
        int power = (int) (Math.sqrt(Math.pow(brightness[y][2 * x], 2) + Math.pow(brightness[y][2 * x + 1], 2)) / 223);
        power = power > 255 ? 255 : power;
        //draw a grayscale color on image "fd"
        fd.setRGB(x, y, new Color(c, c, c).getRGB());
    }
}

draw(fd);

所得到的图像应该看起来像中间的大黑色空间和所有四个角落的白点。通常人们可视化FD,因此零频率出现在图像的中心。所以,如果你需要经典的FD(一个,看起来像reallife图像的星),你需要升级“fd.setRGB(x,y ......”一点:

int w2 = img.getWidth() / 2;
int h2 = img.getHeight() / 2;
int newX = x + w2 >= img.getWidth() ? x - w2  : x + w2;
int newY = y + h2 >= img.getHeight() ? y - h2  : y + h2;

fd.setRGB(newX, newY, new Color(power, power, power).getRGB());

brightnessRGB和绘制懒惰的方法:

public static int brightnessRGB(int rgb) {
    int r = (rgb >> 16) & 0xff;
    int g = (rgb >> 8) & 0xff;
    int b = rgb & 0xff;
    return (r+g+b)/3;
}
private static void draw(BufferedImage img) {
    JLabel picLabel = new JLabel(new ImageIcon(img));
    JPanel jPanelMain = new JPanel();
    jPanelMain.add(picLabel);
    JFrame jFrame = new JFrame();
    jFrame.add(jPanelMain);
    jFrame.pack();
    jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    jFrame.setVisible(true);
}

我知道,我有点迟了,但我只为我的计划做了所有这些。所以,对于那些将从google搜索来到这里的人来说,就这样吧。