画像を動的に取得し、各ピクセルの RGB 値に基づいてピクセルを「バケット」に並べ替える小さな Renderscript を作成しています。バケットの数は変わる可能性があるため、私の本能は配列リストを作成することです。これは明らかに Renderscript 内では不可能なので、スクリプト内で構造体の動的リストを作成する方法を知りたいと思っていました。どんな助けでも大歓迎です。
2 に答える
これには明確な答えはありません。問題は、動的メモリ管理が RenderScript のようなプラットフォームにとって忌み嫌われることです。これは遅く、任意の時点で特定のプロセッサから保証するのは容易ではない可能性があるページ テーブルと TLB に関する多くのことを意味し、ほとんど決して効率的ではありません。やりたいことをやる方法。
適切な代替手段は、バケットが作成された後にバケットをどうするかによって完全に異なります。すべてをバケットに分類せずに、すべてを分類する必要がありますか? ピクセルごとのマスクを作成 (またはアルファ チャネルを使用) し、カテゴリをピクセル データと一緒に保存するだけです。各バケットのサイズに上限はありますか? すべてのバケットをそのサイズに割り当てます。
これが無制限で申し訳ありませんが、メモリ管理は、高性能コードを金切り声で停止させるものの1つです。回避策は必要ですが、適切な回避策は場合によって異なります。
構造体の動的サイズのリストを作成するというタイトルの質問ではなく、ピクセル値を分類するという目標の質問に答えようとします。
あなたのアルゴリズムについてよく知らなくても、2 つのアルゴリズムのいずれかを使用して回答を構成します。
- RGBジョイントヒストグラム
- 隣接するピクセル値を使用しません。
- 接続されたコンポーネント
- 隣接するピクセル値が必要です。
- "Disjoint set"と呼ばれるサポート データ構造が必要です。
よくあるアドバイス。
どちらのアルゴリズムも、ワーカー スレッドごとに大量のメモリを必要とします。また、どちらのアルゴリズムも何らかのランダム メモリ アクセスを必要とするため、GPU にはあまり適していません(注)。したがって、両方のアルゴリズムが CPU 上で実行される可能性があります。したがって、「スレッド」の数を減らして、メモリ要件が増加しないようにすることをお勧めします。
注: 非合体 (非シーケンシャル) メモリ アクセス - 読み取り、書き込み、またはその両方。
RGBジョイントヒストグラム
最良の方法は、Renderscript を使用してジョイント カラー ヒストグラムを計算し、代わりにヒストグラムで (おそらく CPU 上で) 分類アルゴリズムを実行することです。その後、ピクセル単位のラベル割り当ての最終ステップを Renderscript で実行できます。
全体のプロセスは、Google I/O 2013 での Tim Murray の Renderscript プレゼンテーションとほぼ同じです。
ジョイント カラー ヒストグラムには、サイズをハードコーディングする必要があります。たとえば、32x32x32 RGB ジョイント ヒストグラムは 32768 個のヒストグラム ビンを使用します。これにより、各チャンネルで 32 レベルの色合いが可能になります。チャネルあたりのエラーは、256 レベルのうち +/- 2 レベルになります。
接続されたコンポーネント
Renderscript にマルチスレッドの接続されたコンポーネントのラベル付けを正常に実装しました。私の実装は CPU での実行に限定されていることに注意してください。私の実装を GPU で実行することはできません。
前提条件。
- Union-Find アルゴリズム (およびパス圧縮やランキングなどのさまざまな理論的部分) と、それが接続要素のラベル付けにどのように役立つかを理解します。
いくつかのデザインの選択。
- 「リンク」を格納するために、画像と同じサイズの 32 ビット整数配列を使用します。
- リンクは Union-Find と同じ方法で行われますが、ランキングの利点がない点が異なります。これは、ツリーが非常に不均衡になり、パスの長さが長くなる可能性があることを意味します。
- 一方で、アルゴリズムのさまざまなステップでパス圧縮を実行します。これは、パス (深さ) を短くすることによって、最適ではないツリー マージのリスクを相殺します。
小さいながらも重要な実装の詳細。
- 整数配列に格納された値は、基本的に、(i) ピクセルが独自のルートである場合はそれ自体、または (ii) 現在のピクセルと同じラベルを持つ別のピクセルへの "(x, y)" 座標のエンコードです。ピクセル。
ステップ。
- マルチスレッドステージ。
- 画像を小さなタイルに分割します。
- 各タイル内で、そのタイルにローカルなラベル値を使用して、連結成分を計算します。
- 各タイル内でパス圧縮を実行します。
- ラベル値をグローバル座標に変換し、タイルのラベルをメインの結果マトリックスにコピーします。
- シングルスレッドステージ。
- 横縫い。
- 縦縫い。
- パス圧縮のグローバル ラウンド。