Java数组操作

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

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; } 

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

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

 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等)的广义resize例程真的很难。 您需要定义一种方法来确定子像素的值 - 像素之间的点 - 以获得更复杂的因子,例如0.13243。 这当然很容易做到,你可以开发一个非常幼稚的线性插值原理,当你需要两个像素之间的值时,你只需要拍摄周围的像素,在它们的值之间构造一条线,然后读取子像素从线上指出。 更复杂的插值版本可能是基于sinc的插值...或广泛发表的文献中的许多其他插值之一。

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

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

你有什么是可以理解的,我认为它一个O(n ^ 4)算法。 Ouchies!

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

关于错误,运行两次,一次使用具有偶数长度(6×6)和另一个奇数(7×7)的输入数组。 当你在它时,6×7和7×6。

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

 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,你将得到错误的结果。