我有一个名为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;
}
答案 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]
为我们提供了“当前”像素。
同样,newr
和newc
索引到指定为hi
的“半图像”矩阵。对于newr
或newc
中的每个增量,我们分别将r
和c
增加2。通过这样做,我们在迭代图像时跳过所有其他像素。
写一个不适用于小数量(如1 / 2,1 / 4,1 / 8等)的广义调整大小例程真的很难。您需要定义一种方法来确定子像素的值 - 像素之间的点 - 用于更复杂的因子,例如0.13243。这当然很容易做到,你可以开发一个非常天真的线性插值原理,当你需要两个像素之间的值时,你只需要拍摄周围的像素,在它们的值之间构造一条线,然后读取子像素从线上指出。更复杂的插值版本可能是基于sinc
的插值...或广泛发表的文献中的众多其他插值之一。
放大图像的大小涉及的东西与我们在这里做的有点不同(如果你实际上必须编写一个通用的resize函数,你可能会考虑拆分你的函数以不同的方式处理升级和缩减)。你需要以某种方式创建比原来更多的值 - 那些插值函数也适用于此。一个简单的方法可能只是在点之间重复一个值,直到你有足够的,并且稍微有点变化,你可能从左边那么多的值,从右边那么多的特定位置。
我鼓励你去思考 - 因为这是家庭作业,我将远离实施 - 将缩放因子视为导致你对一个图像进行观察的东西,并写在新图片。当缩放系数小于1时,您通常从原始图像中采样以填充新图像并忽略原始图像的某些像素。当缩放系数大于1时,您通常会更频繁地写入新图像,并且可能需要从旧图像中多次读取相同的值。 (我做的很差,突出了这里的差异,希望你能看到我所面临的二元论。)
答案 1 :(得分:0)
你所拥有的是非常容易理解的,我认为 IS 是一种O(n ^ 4)算法。 Ouchies!
您可以通过将i*scale
和j*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,并且你将得到错误的结果。