3

Android デバイス用のビットマップ操作アルゴリズムを作成しようとしているときに問題が発生しました。

1680x128 ピクセルのビットマップがあり、フィルターを適用する必要があります。しかし、この非常に単純なコード片は、私の Android デバイス (1Ghz プロセッサを搭載した xperia ray) で実際に実行するのに約 15 ~ 20 秒かかりました。

そのため、ボトルネックを見つけようとし、できるだけ多くのコード行を削減して、実行にほぼ同じ時間を要したループ自体に行き着きました。

for (int j = 0; j < 128; j++) {
    for (int i = 0; i < 1680; i++) {
         Double test = Math.random();
    }
}

このようなデバイスが、難しい操作のない単純な for ループで非常に多くの時間を費やすのは正常ですか?

私はモバイルデバイスでのプログラミングに非常に慣れていないため、この質問がばかげている場合はご容赦ください。

更新: いくつかの簡単な操作でより高速になりました。

しかし、私の主な問題に戻ります:

public static void filterImage(Bitmap img, FilterStrategy filter) {
    img.prepareToDraw();
    int height = img.getHeight();
    int width = img.getWidth();
            RGB rgb;
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            rgb = new RGB(img.getPixel(i, j));
            if (filter.isBlack(rgb)) {
                img.setPixel(i, j, 0);
            } else
                img.setPixel(i, j, 0xffffffff);
        }
    }
    return;
}

上記のコードは、デバイス上でより高速に実行するために本当に必要なものです。(ほぼ即時) 最適化の可能性はありますか?

RGB は、赤、緑、青の値を計算するクラスにすぎず、3 つの色部分すべてが 100 または指定された値を下回る場合、フィルターは単純に true を返します。img.getPixel(i,j) または setPixel のループにはすでに 20 秒以上かかります。これはそんなに高価な操作ですか?

4

4 に答える 4

3

作成されているタイプ Double のオブジェクトが多すぎるためである可能性があります..したがって、ヒープサイズが増加し、デバイスがフリーズし始めます..

回避策は

double[] arr = new double[128]
for (int j = 0; j < 128; j++) {
    for (int i = 0; i < 1680; i++) {
         arr[i]  = Math.random();
    }
}
于 2012-04-12T10:07:43.903 に答える
2

まず第一に、Stephen C は良い議論をしています: RGB オブジェクトの束を作成しないようにしてください。

getPixel次に、比較的高価な への呼び出しをへの 1 回の呼び出しに置き換えることで、大幅な改善が可能getPixels

簡単なテストを行ったところ、ランタイムを約 10% まで削減することができました。やってみて。これは私が使用したコードです:

int[] pixels = new int[height * width];
img.getPixels(pixels, 0, width, 0, 0, width, height);

for(int pixel:pixels) {
    // check the pixel
}
于 2012-04-12T11:56:22.540 に答える
1

以下のドキュメントには、パフォーマンスに影響を与える可能性のあるランダムに関する免責事項があります。静的バージョンを使用するのではなく、自分でインスタンスを作成してみてください。パフォーマンスに関する免責事項を太字で強調しています。

n >= 0.0 && n < 1.0 の擬似乱数 double n を返します。このメソッドは、Random の単一のインスタンスを再利用します。Random へのアクセスが同期されるため、このメソッドはスレッドセーフですが、スケーラビリティが損なわれます。アプリケーションは、各スレッドに Random を割り当てることでパフォーマンス上の利点を得ることができます。

同期アクセスを回避するために、クラスの静的フィールドとして独自のランダムを作成してみてください。

private static Random random = new Random();

次に、次のように使用します。

double r = random.nextDouble();

倍精度が必要ない場合は、float (random.nextFloat()) の使用も検討してください。

于 2012-04-12T10:14:41.370 に答える
0

RGB は、赤、緑、青の値を計算するクラスにすぎず、3 つの色部分すべてが 100 または指定された値を下回る場合、フィルターは単純に true を返します。

height * width問題の 1 つは、単一のピクセルが黒かどうかをテストするためだけに、RGB クラスのインスタンスを作成していることです。そのメソッドを、テストするピクセルを引数として受け取る静的メソッド呼び出しに置き換えます。


より一般的には、一部のコードが遅い理由がわからない場合は、プロファイルを作成します。この場合、プロファイラーは、RGB コンストラクターでかなりの時間が費やされていることを通知します。また、メモリ プロファイラは、多数の RGB オブジェクトが作成され、ガベージ コレクションが行われていることを示します。

于 2012-04-12T11:09:37.493 に答える