ダウンサンプリングを含むデモザイクアルゴリズム 質問する

ダウンサンプリングを含むデモザイクアルゴリズム 質問する

はじめに: 私が取り組んでいること。

みなさん、こんにちは!私は、ベイヤーパターンを持つ画像を赤、緑、青のチャンネルを表す画像に変換するために使用するデモザイク アルゴリズムに取り組んでいます。このアルゴリズムに次の特性を持たせたいと考えています。

  1. 可能な限り多くの生の情報を保存します。

  2. ノイズ除去が行われない場合でも、画像の詳細が不明瞭になることはありません。

  3. アーティファクトは可能な限り少なくなります。

  4. モザイク画像のサイズが N x N の場合、3 つのカラー画像のサイズはそれぞれ N/2 x N/2 になります。

  5. アルゴリズムは高速である必要があります。「高速」という言葉の意味を理解するために、こう言わせていただきます。双線形補間を使用する OpenCV のアルゴリズムよりも少なくとも 2 倍高速なもので満足します。

これまでに私が達成したこと。

これまで、私は双線形補間を使用してモザイク画像の半分のサイズの3つの画像を生成するアルゴリズムを考案しました。アルゴリズムはおよそ3~4倍速いCV_BayerBG2BGR 変換 (双線形補間) を実行する OpenCV の cvtColor アルゴリズムよりも優れています。

ベイヤーパターンの仕組みを理解するには、以下のスケッチを参照してください。円でマークされたポイントで補間を実行します。数字は、黒い円でマークされたポイントで補間値を取得するために、基になるピクセルに掛ける係数を表します。

ここに画像の説明を入力してください

私のアルゴリズムの結果は以下で確認できます。OpenCV で使用できる両方のデモザイク アルゴリズム (双線形補間と可変数の勾配) の結果も追加しました。比較すると私のアルゴリズムの結果は非常に劣っているように見えますが、OpenCV の双線形補間の結果はダウンサンプリングするとほぼ同じに見えることに注意してください。これは、基礎となるアルゴリズムが同じであるため当然予想されます。

ここに画像の説明を入力してください

...それでは最後に質問です。

現在のソリューションは、私のプロジェクトに許容できる結果をもたらし、許容できる速度も出しています。ただし、上記の 5 つの基準のいずれかが改善されるのであれば、最大 2 倍遅いアルゴリズムを使用してもかまいません。そこで疑問が浮かびます。パフォーマンスを大幅に低下させることなくアルゴリズムを改善するにはどうすればよいですか?

私はこのタスクに十分なプログラミング経験があるので、特にコード スニペットを求めているわけではありません。あらゆる種類の回答 (コード、リンク、提案、特に過去の経験に基づくもの) を歓迎します。

追加情報:

  • 私はC++で作業しています。
  • アルゴリズムは高度に最適化されており、SSE 命令を使用し、非並列です。
  • 私は大きな画像(数 MB)を扱っていますが、キャッシュを認識し、画像を複数回通過することを避けることが非常に重要です。

私は一般的なプログラミングのアドバイス(一般的な最適化など)を求めているわけではありませんが、一方で、タスク固有の回答があれば大歓迎です。よろしくお願いします。

ベストアンサー1

サンプルをフィルタリングすることで、高品質の結果が得られます。ナイキスト周波数通常、これはサンプル レートの半分ですが、この場合、赤と青のサンプルはピクセル レートの 1/2 でしか取得されないため、ナイキストはサンプル レートの 1/4 になります。サイズを変更するときは、入力と出力のナイキスト レートの低い方にフィルターする必要がありますが、出力は入力の 1/2 であるため、再度 1/4 にフィルターする必要があります。

完璧なフィルターはシンク関数; カットオフ周波数以下の信号は100%出力し、カットオフ周波数以上の信号は出力しません。残念ながら、無限に拡張されるため、完全に非実用的です。実用的なアプリケーションでは、代わりにウィンドウ付きSincが使用されます。最も一般的なものは、ランチョス核ウィンドウ サイズは品質と速度に基づいて選択され、次数が高いほど理想的な Sinc 関数に近くなります。あなたの場合は速度が最も重要であるため、Lanczos2 をお勧めします。

フィルターのカットオフ周波数は、フィルターの幅に反比例します。この場合、カットオフを通常のカットオフの半分にしたいので、フィルターは通常の幅の 2 倍に引き伸ばされます。通常、Lanczos2 フィルターには、中心点から+ /- 2 ピクセルまでの入力が必要ですが、2 ピクセル引き伸ばすには、中心から+ /- 4までの入力が必要です。

適切なカットオフ フィルターがあれば、中心点の選択は完全に任意です。あなたの場合、4 つのサンプル ポイントの中間点を選択しました。代わりに、入力サンプルの 1 つに正確に一致する点を選択すると、興味深いことが起こります。フィルター係数の多くがゼロになり、それらのピクセルを計算に含める必要がなくなります。以下の例では、赤のピクセルを中心にしましたが、赤のピクセルにはまったくフィルター処理が必要ないことがわかります。次の図は、Lanczos2 フィルター値が各色の合計が 1.0 になるようにスケーリングされた図と、その結果の式を示しています。

ベイヤーマトリックス上のLanczos2

red = p[x][y]
green = (p[x][y-3] + p[x-3][y] + p[x+3][y] + p[x][y+3]) * -0.03125 +
        (p[x][y-1] + p[x-1][y] + p[x+1][y] + p[x][y+1]) * 0.28125
blue = (p[x-3][y-3] + p[x+3][y-3] + p[x-3][y+3] + p[x+3][y+3]) * 0.00391 +
       (p[x-1][y-3] + p[x+1][y-3] + p[x-3][y-1] + p[x+3][y-1] + p[x-3][y+1] + p[x+3][y+1] + p[x-1][y+3] + p[x+1][y+3]) * -0.03516 +
       (p[x-1][y-1] + p[x+1][y-1] + p[x-1][y+1] + p[x+1][y+1]) * 0.31641

すべてを整数領域内に保持したい場合は、固定小数点数でもこの方法がうまく機能します。

red = p[x][y]
green = ((p[x][y-3] + p[x-3][y] + p[x+3][y] + p[x][y+3]) * -32 +
         (p[x][y-1] + p[x-1][y] + p[x+1][y] + p[x][y+1]) * 288) >> 10
blue = ((p[x-3][y-3] + p[x+3][y-3] + p[x-3][y+3] + p[x+3][y+3]) * 4 +
        (p[x-1][y-3] + p[x+1][y-3] + p[x-3][y-1] + p[x+3][y-1] + p[x-3][y+1] + p[x+3][y+1] + p[x-1][y+3] + p[x+1][y+3]) * -36 +
        (p[x-1][y-1] + p[x+1][y-1] + p[x-1][y+1] + p[x+1][y+1]) * 324) >> 10

緑と青のピクセル値は 0 から最大の範囲外になる可能性があるため、計算が完了したらそれらをクランプする必要があります。

おすすめ記事