2

私の場合、基本的に ARGB-float-Arrays である Cocoa Touch で vImages を使用しており、サブサンプリングを行う必要があります。ローパス フィルタリングは vImage 関数を使用しても問題ありませんが、2x2 ピクセルから 1 つを選択するにはどうすればよいですか (係数 2 でサブサンプリングしたい場合)。もちろん、vDSP ストライド関数を使用することもできますが、これは水平サブサンプリングでのみ機能し、垂直サブサンプリングでは機能しません。

以下が私が何をしようとしているのかを明確にすることを願っています。この画像に示すように、X でマークされたすべてのピクセルを選択したいと思います。

X O X O X O
O O O O O O
X O X O X O
O O O O O O
X O X O X O
O O O O O O

しかし、メモリは線形であるため、私の配列は次のようになります。

X O X O X O O O O O O O X O X O X O O O O O O O X O X O X O O O O O O O

合理的な方法でサブサンプリングを実行するにはどうすればよいですか?

編集: 1 次元 float-array (負の値を含む) として格納されている特定のビットマップの 2 次元ダウンサンプリングを行う効率的な方法を探しています。

4

4 に答える 4

1

現実には、この種のサブサンプリングを実行しているとき、実行できる賢いものは実際にはありません。ストライドメモリアクセスでは、多くのトリックを高速化することはできません。そのため、使用するライブラリコードは、数分で自分で作成できるCコードと基本的に同等になります。単純なC実装を使用します。

これはGPUでかなり効率的に実行できると思いますが、データがすでにGPUコンテキストにある場合を除いて、パフォーマンスを向上させることはできません。最初にそこにデータを転送する必要がある場合、そのコストは実際の操作でのパフォーマンスの節約を圧倒します。

于 2012-08-18T13:30:28.453 に答える
0

これはほとんど「ポインターの使い方」の問題に過ぎないことを認識しています。ただし、実行しようとしている操作では、高品質の画像は得られません。ピクセル化されたように見え、一部の詳細が拡大され、他の詳細が失われます。

幸いなことに、画像のリサンプリング手法は十分に研究されている分野であり、ここには多くのオプションがあります。

GPU を使用している場合、説明する操作は、OpenCL または OpenGL で最も近いサンプリング方法にすぎないため、必要な座標を計算して最も近いものを選択するだけです。おそらく、線形サンプリング法の方が見栄えが良いでしょう。

CPU を使用している場合は、いくつかのオプションがあります。データが CGImageRef に保持されている場合、スケーリングを使用して CGBitmapContextRef にレンダリングし、各次元で画像のサイズを 2 分の 1 に縮小できます。これにより線形リサンプリングが得られると思いますが、その詳細はどこかで入手できるはずです。

データが C 配列にある場合は、vImageScale_ARGBFFFF() が役に立ちます。元の 1/2 の高さと 1/2 の幅の新しいバッファーを作成し、その関数を使用して適切な値にダウンサンプリングするだけです。これは Lanczos のリサンプリングを使用します。これは少し遅くなりますが、見栄えが良くなります。(おそらく、浮動小数点データの方が適しています。高忠実度が必要なため、選択したと思います。) Lanczos カーネルには、ローパス フィルター処理とダウンサンプリングを 1 つのパスに組み合わせるという利点があるため、実行することが少なくなります。

于 2014-01-21T02:16:57.260 に答える
0

私はいつもこれを行っています - 画像の幅を知る必要があります。つまり、ポインターがあり、1 つの行に対して 1 つおきのピクセルを取得し、次にポインターを行全体にぶつけてから、行の最後に到達するまで 1 つおきのピクセルを取り始め、次にポインターを 1 行全体にぶつけます。

私にとって、私は通常、画像をビットマップコンテキストにレンダリングしているので、ピクセルあたりのバイト数、ピクセル単位の幅、および行あたりのバイト数を知っています(ポインターをバンプするためですが、幅 x だけかもしれません)ピクセルあたりのバイト数)。

編集:申し訳ありませんが明確ではありませんでした。x 列と y 行のビットマップを指定して、新しい CGBitMapContext を作成し、上記のサンプルを使用して「1 つおき」のピクセルを取得し、この新しいコンテキストに書き込みます。これで、質問で必要なピクセルと正確に一致する場合、2 番目のビットマップができました。そのビットマップを使用して、必要な処理をさらに適用できます。

于 2012-08-16T23:31:09.867 に答える
0

メモリは線形であるため、ソース マトリックスを幅が 2 倍、高さが半分のマトリックスとして解釈します。

X O X O X O  O O O O O O
X O X O X O  O O O O O O
X O X O X O  O O O O O O

インターリーブ (ストライド = 2) でコピーすると、次のようになります。

X X X  O O O
X X X  O O O
X X X  O O O

次に、vDSP_mmov左側の部分行列を結果の部分行列にコピーするために使用します。

インターリーブによるコピー (第 1 フェーズ) にはvDSP_zvmov関数を使用できますが、float には最適化されていません。おそらくas scalar param を使用すると、より高速に動作しますvDSP_vsadd0

于 2012-11-30T20:09:56.353 に答える