1

処理中にpngをロードしています。この png には、実際の画像の周囲に多くの未使用のピクセルがあります。幸いなことに、これらのピクセルはすべて完全に透明です。私の目標は、png をトリミングして画像のみを表示し、未使用のピクセルを取り除くことです。最初のステップは、画像の境界を計算することです。最初に、すべてのピクセルのアルファ値をチェックし、そのピクセルが境界の最高または最低の座標であるかどうかを確認したかったのです。このような:

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

次に、最初の非アルファピクセルまでこれを実行し、最高の座標境界に対して逆方向に繰り返すだけでよいことに気付きました。このような:

------
-->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 に答える