Java数组操作

时间:2010-10-08 00:08:28

标签: java arrays

我有一个名为resize的函数,它接受一个源数组,并调整为新的宽度和高度。我认为,我使用的方法效率低下。我听说有更好的方法。无论如何,当scale是int时,下面的代码可以工作。但是,有一个名为half的第二个函数,它使用resize将图像缩小一半。所以我将scale设为double,并使用类型转换将其转换回int。这种方法不起作用,我不知道错误是什么(教师使用他自己的评分和测试这些功能,而不是通过它)。你能发现错误,还是有更有效的方法来制作调整大小功能?

public static int[][] resize(int[][] source, int newWidth, int newHeight) {

        int[][] newImage=new int[newWidth][newHeight];
        double scale=newWidth/(source.length);
        for(int i=0;i<newWidth/scale;i++)
            for(int j=0;j<newHeight/scale;j++)
                for (int s1=0;s1<scale;s1++) 
                    for (int s2=0;s2<scale;s2++) 
                        newImage[(int)(i*scale+s1)][(int)(j*scale+s2)] =source[i][j];

        return newImage; 
    }

    /**
     * Half the size of the image. This method should be just one line! Just
     * delegate the work to resize()!
     */
    public static int[][] half(int[][] source) {
        int[][] newImage=new int[source.length/2][source[0].length/2];
        newImage=resize(source,source.length/2,source[0].length/2);
        return newImage;
    }

3 个答案:

答案 0 :(得分:1)

因此,一种改变图像大小的方案是重新采样(从技术上讲,这是唯一的方法,每种变化实际上只是一种不同的重采样功能)。

将图像切成两半非常容易,您希望在每个方向上读取每个其他像素,然后将该像素加载到新的半角数组中。困难的部分是确保你的簿记能力很强。

static int[][] halfImage(int[][] orig){
    int[][] hi = new int[orig.length/2][orig[0].length/2];

    for(int r = 0, newr = 0; r < orig.length; r += 2, newr++){
        for(int c = 0, newc = 0; c < orig[0].length; c += 2, newc++){
            hi[newr][newc] = orig[r][c];
        }
    }

    return hi;
}

在上面的代码中,我索引到原始图像,读取从第0行和第0列开始的每隔一行中的每隔一个像素(假设图像是行主要,这里)。因此,r告诉我们正在查看原始图片中的哪一行,c告诉我们原始图片中的哪一列我们正在查看。 orig[r][c]为我们提供了“当前”像素。

同样,newrnewc索引到指定为hi的“半图像”矩阵。对于newrnewc中的每个增量,我们分别将rc增加2。通过这样做,我们在迭代图像时跳过所有其他像素。

写一个不适用于小数量(如1 / 2,1 / 4,1 / 8等)的广义调整大小例程真的很难。您需要定义一种方法来确定子像素的值 - 像素之间的点 - 用于更复杂的因子,例如0.13243。这当然很容易做到,你可以开发一个非常天真的线性插值原理,当你需要两个像素之间的值时,你只需要拍摄周围的像素,在它们的值之间构造一条线,然后读取子像素从线上指出。更复杂的插值版本可能是基于sinc的插值...或广泛发表的文献中的众多其他插值之一。

放大图像的大小涉及的东西与我们在这里做的有点不同(如果你实际上必须编写一个通用的resize函数,你可能会考虑拆分你的函数以不同的方式处理升级和缩减)。你需要以某种方式创建比原来更多的值 - 那些插值函数也适用于此。一个简单的方法可能只是在点之间重复一个值,直到你有足够的,并且稍微有点变化,你可能从左边那么多的值,从右边那么多的特定位置。

我鼓励你去思考 - 因为这是家庭作业,我将远离实施 - 将缩放因子视为导致你对一个图像进行观察的东西,并写在新图片。当缩放系数小于1时,您通常从原始图像中采样以填充新图像并忽略原始图像的某些像素。当缩放系数大于1时,您通常会更频繁地写入新图像,并且可能需要从旧图像中多次读取相同的值。 (我做的很差,突出了这里的差异,希望你能看到我所面临的二元论。)

答案 1 :(得分:0)

你所拥有的是非常容易理解的,我认为 IS 是一种O(n ^ 4)算法。 Ouchies!

您可以通过将i*scalej*scale推出内部两个循环来稍微改善它们 - 它们现在处于不变的状态。但是,优化器可能会为您执行此操作。还有一些其他类似的优化。

关于错误,运行两次,一次使用具有偶数长度(6x6)的输入数组和另一个具有奇数(7x7)的输入数组。你可以使用6x7和7x6。

答案 2 :(得分:0)

根据您的其他问题,您似乎可能在混合类型方面遇到问题 - 使用数字转换。实现此目的的一种方法是将有问题的行拆分为多行,这可以使您的代码更易于调试,并且对不熟悉问题空间的其他人更具可读性。每个次要操作都是一行,直到达到最终值。例如,

newImage[(int)(i*scale+s1)][(int)(j*scale+s2)] =source[i][j];

会变成

int x = i * scale;
x += s1;
int y = j* scale;
y +=s2;

newImage[x][y] = source[i][j];

现在,您可以在调试器中运行代码,并在执行每个操作后查看每个项的值。如果某个值与您认为的值不匹配,请查看它并找出原因。

现在,回到可疑问题:我希望您需要在某处使用双打,而不是整数 - 在您谈到缩放因子的另一个问题中。因子是否小于1?如果是这样,当它被转换为int时,它将为0,并且你将得到错误的结果。

相关问题