仿射变换与插值

4
我希望对一个非常低分辨率的位图进行仿射变换,同时保留尽可能多的信息。我的输入数据是一张手写字符的1位64x64像素图像,输出将是灰度和更高分辨率的图像。通过分析图像,我构建了一系列仿射变换(旋转、缩放、剪切、平移),可以将它们相乘成一个单一的仿射变换矩阵。我的问题是,鉴于输入图像和计算出的仿射变换矩阵,如何以最高可能的质量计算输出图像?我已经阅读了有关不同插值技术的文章,但所有这些文章都是关于如何进行缩放的插值,而不是关于一般仿射变换的插值。这里有一个演示,正好做到了我想要的效果。给定一个仿射变换矩阵和插值技术,它可以计算出一张图像。

http://bigwww.epfl.ch/demo/jaffine/index.html

如果我有一个低分辨率的1位输入和一个给定的T仿射变换矩阵,那么计算更高分辨率(例如4倍)灰度图像需要哪些步骤?

你能否提供一些关于如何使用仿射变换实现线性、立方或更好的插值的源代码教程文章甚至是书籍的链接?

我需要在Java中实现这个问题,我知道Java有一个Affine类,但我不知道它是否实现了插值。你知道有没有C++或Java库可以使用漂亮易读的代码来解决如何使用插值进行仿射变换的算法吗?

有没有免费可用的Java或C++库,内置用于计算使用插值的仿射变换的函数?


3
使用Java2D API可以进行带有抗锯齿功能的仿射变换。 - Sibbo
你是否考虑过使用可缩放矢量图像(SVG)而不是标准位图图像?Apache的Batik库与Java兼容,可以为您处理此问题。 - Hovercraft Full Of Eels
@sibbo:这对形状有帮助,但对位图图像没有帮助。 - Hovercraft Full Of Eels
zsero:请查看这里,这里有一份不错的解释,介绍了在转换位图时可使用的各种插值类型:几何图像操作。 特别注意第8.2节。基于此,您是否尝试过设置RenderingHints以使用其中一种双三次插值类型,例如INTERP_BICUBIC或INTERP_BICUBIC2? - Hovercraft Full Of Eels
3
微软研究院有一篇令人惊叹的论文,介绍了将像素艺术转化为矢量图形的方法。如果您对最新的发展感兴趣,请查看此链接:http://research.microsoft.com/en-us/um/people/kopf/pixelart/index.html - vhallac
显示剩余3条评论
2个回答

1

好的,这就是最终我想到的解决方案。

我将所有的数组[][]转换为BufferedImage对象:
static BufferedImage BImageFrom2DArray(float data[][]) {
    int width = data.length;
    int height = data[0].length;
    BufferedImage myimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            int value = (int) ((1f - data[x][y]) * 255f);
            myimage.setRGB(y, x, (value << 16) | (value << 8) | value);
        }
    }
    return myimage;
}

使用AffineTransformOp应用仿射变换,插值方法为双三次:
    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BICUBIC);
    BufferedImage im_transformed = op.filter(im_src, null);

将BufferedImage对象转换回数组[][]:
static float[][] ArrayFromBImage(BufferedImage bimage, int width, int height) {
    int max_x = bimage.getWidth();
    int max_y = bimage.getHeight();
    float[][] array = new float[width][height];
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            float red, alpha, value;
            int color;
            if (x >= max_x || y >= max_y) {
                array[y][x] = 0;
            } else {
                color = bimage.getRGB(x, y);
                alpha = (color >> 24) & 0xFF;
                red = (color >> 16) & 0xFF;
                value = 1f - red / 255;
                if (alpha == 0) {
                    array[y][x] = 0;
                } else {
                    array[y][x] = value;
                }
            }
        }
    }
    return array;
}

1
你链接的那些人有一个带有多种插值选项的C实现这里。你可以使用JNI来包装它。还有JavaCV,它包装了OpenCV。OpenCV包含了具有插值功能的warpAffine。此外,还要查看Java高级图像API 这里

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接