【问题标题】:ArrayIndexOutOfBoundsException while calculating Mean / Average values from array of pixelsArrayIndexOutOfBoundsException 从像素数组计算平均值/平均值
【发布时间】:2013-08-06 08:00:01
【问题描述】:

我正在尝试使用位图在 Android 中实现平均/平均 3x3 过滤器。

每次我尝试应用此过滤器时,应用程序都会继续关闭。当我尝试在图像上应用此过滤器时出现 ArrayIndexOutOfBoundsException 错误。

我的代码如下:

    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {

            int index = 0;

            for (int filterX = -filterWidth / 2; filterX < filterWidth / 2; filterX++) {
                for (int filterY = -filterHeight / 2; filterY < filterHeight / 2; filterY++) {

                    A = (pixels[x+filterX+width*(y+filterY)])>>24 & 0xFF;
                    R = (pixels[x+filterX+width*(y+filterY)] >> 16) & 0xFF;
                    G = (pixels[x+filterX+width*(y+filterY)] >> 8) & 0xFF;
                    B = pixels[x+filterX+width*(y+filterY)] & 0xFF;


                        }
                }
       }
 }

【问题讨论】:

  • 请发布堆栈跟踪并指出导致异常的行。
  • @JasonC 如何获取堆栈跟踪数据?

标签: java android arrays bitmap pixel


【解决方案1】:

你没有显示堆栈跟踪(编辑:现在你显示了,谢谢),这将表明哪一行引发了异常。

但乍一看,您的问题似乎在这里:

for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
        int index = 0;
        for (int filterX = -filterWidth / 2; filterX < filterWidth / 2; filterX++) {
            for (int filterY = -filterHeight / 2; filterY < filterHeight / 2; filterY++) {
                A = (pixels[x+filterX+width*(y+filterY)])>>24 & 0xFF;
                R = (pixels[x+filterX+width*(y+filterY)] >> 16) & 0xFF;
                G = (pixels[x+filterX+width*(y+filterY)] >> 8) & 0xFF;
                B = pixels[x+filterX+width*(y+filterY)] & 0xFF;
                ...
            } 
        }
    }
 }

您超出了像素数组的范围,因为您尝试将 3x3 滤镜直接应用于图像边缘,因此滤镜超出了图像范围。考虑您的第一次迭代:

  • x = 0
  • y = 0
  • filterX = -filterWidth / 2 = -3 / 2 = -1
  • filterY = -filterHeight / 2 = -3 / 2 = -1

然后你尝试访问pixels[x+filterX+width*(y+filterY)]:

  • 0 + -1 + 宽度 * (0 + -1)
  • = -1 + -宽度

所以你可以看到,访问pixels[-1 + -width] 显然是越界的。如果您的 filterX/filterY 循环正确,上限也会发生同样的情况(请参阅此答案底部的注释 - 目前您的大小为 3,filterX 和 filterY 停止在 0,而不是 1)。

您要么不需要在距离边缘的 filterWidth/2(或 filterHeight/2 垂直)像素内应用滤镜,要么在读取图像像素时需要进行一些边界检查,并将边缘以外的区域视为 0 .

一种可能的优化是在您的图像周围创建一个 filterWidth/2(或 filterHeight/2 垂直)黑色边框,并且不处理边缘附近的那些像素。那么你就不需要分支来进行边界检查了。

顺便说一句,对于奇数大小的过滤器,您需要在循环中执行 &lt;= filterWidth / 2(高度相同):

for (int filterX = -filterWidth / 2; filterX <= filterWidth / 2; filterX++) {
    for (int filterY = -filterHeight / 2; filterY <= filterHeight / 2; filterY++) {

这适用于所有奇数大小的过滤器。

【讨论】:

  • 谢谢。这似乎证实了我的怀疑。
  • @User1204501 你的意思是 filterX/filterY 循环?我在最后做了一个注释。我会努力改进的。给我一分钟。
  • 有很多问题要问。 :) 您应该能够自己制定边界检查逻辑(确定您在图像中读取位置的 x 和 y 坐标 [easy, x+filterX and y+filterY],检查 0 和图像宽度/高度,相应地剪辑)。我会先做一个简单的边界检查,然后仅在您的性能不符合您的要求时才考虑其他优化(例如创建填充边框)。
  • 我没有做任何边缘检测atm。因此,只需将前两个 for 循环替换为: for (int x = 3; x
  • 是的,应该可以的。如果您想支持其他尺寸的过滤器,您可以使用size/2 而不是3(对于尺寸为 3 的过滤器,您实际上可以使用 1 而不是 3)。
猜你喜欢
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 2013-01-14
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
相关资源
最近更新 更多