1

我正在处理中加载一个png。这个 png 在实际图像周围有很多未使用的像素。幸运的是,所有这些像素都是完全透明的。我的目标是裁剪 png 以仅显示图像并去除未使用的像素。第一步是计算图像的边界。最初我想检查每个像素的 alpha 值,看看该像素是边界的最高坐标还是最低坐标。像这样:

------
------
--->oo
oooooo
oooooo

然后我意识到我只需要这样做直到第一个非 alpha 像素并向后重复它以获得最高坐标界限。像这样:

------
-->ooo
oooooo
ooo<--
------

这将意味着更少的计算相同的结果。然而,我从中得到的代码似乎仍然非常复杂。这里是:

class Rect {  //class for storing the boundries
  int xMin, xMax, yMin, yMax;
  Rect() {

  }
}

PImage gfx;

void setup() {
  size(800, 600);
  gfx = loadImage("resources/test.png");
  Rect _bounds = calcBounds();  //first calculate the boundries
  cropImage(_bounds);  //then crop the image using those boundries
}

void draw() {

}

Rect calcBounds() {
  Rect _bounds = new Rect();
  boolean _coordFound = false;
  gfx.loadPixels();

  //x min bounds
  for (int i = 0; i < gfx.width; i++) {  //rows
    for (int i2 = 0; i2 < gfx.height; i2++) {  //columns
      if (alpha(gfx.pixels[(gfx.width * i2) + i]) != 0) {
        _bounds.xMin = i;
        _coordFound = true;
        break;
      }
    }
    if (_coordFound) { 
      break;
    }
  }

  //x max bounds
  _coordFound = false;
  for (int i = gfx.width - 1; i >= 0; i--) {  //rows
    for (int i2 = gfx.height - 1; i2 >= 0; i2--) {  //columns
      if (alpha(gfx.pixels[(gfx.width * i2) + i]) != 0) {
        _bounds.xMax = i;
        _coordFound = true;
        break;
      }
    }
    if (_coordFound) { 
      break;
    }
  }

  //y min bounds
  _coordFound = false;
  for (int i = 0; i < gfx.height; i++) {  //columns
    for (int i2 = 0; i2 < gfx.width; i2++) {  //rows
      if (alpha(gfx.pixels[(gfx.width * i) + i2]) != 0) {
        _bounds.yMin = i;
        _coordFound = true;
        break;
      }
    }
    if (_coordFound) { 
      break;
    }
  }

  //y max bounds
  _coordFound = false;
  for (int i = gfx.height - 1; i >= 0; i--) {  //columns
    for (int i2 = gfx.width -1; i2 >= 0; i2--) {  //rows
      if (alpha(gfx.pixels[(gfx.width * i) + i2]) != 0) {
        _bounds.yMax = i;
        _coordFound = true;
        break;
      }
    }
    if (_coordFound) { 
      break;
    }
  }

  return _bounds;
}

void cropImage(Rect _bounds) {
  PImage _temp = createImage((_bounds.xMax - _bounds.xMin) + 1, (_bounds.yMax - _bounds.yMin) + 1, ARGB);
  _temp.copy(gfx, _bounds.xMin, _bounds.yMin, (_bounds.xMax - _bounds.xMin) + 1, (_bounds.yMax - _bounds.yMin)+ 1, 0, 0, _temp.width, _temp.height);
  gfx = _temp;  //now the image is cropped
}

没有更有效/更快的方法来计算图像的边界吗?而且我仍然希望之后的边界坐标,而不是在计算过程中切掉图像。

4

1 回答 1

1

如果您将找到的最后一个完全空行存储在变量中,例如水平最小和最大扫描,您可以使用它将垂直扫描限制在尚未检查为空的区域,而不必扫描完整列。取决于可裁剪区域的数量和形状,可以为您节省很多 - 请参阅示意图以获取修改后算法的直观说明:

优化示意图


顺便说一句,在您的//x min bounds扫描中,您似乎在两个循环的宽度上进行迭代for,但应该是一个高度吗?(当然,除非你的图像都是方形的:))

于 2013-07-28T09:22:36.930 回答