タコやりたいなと思いつつ触れてない間に同僚が全部クリアしていて、
うわぁと思っているプログラマの某(なにがし)です。
【画像のリサイズを実装する(ニアレストネイバー編)】
↑前回、画像のリサイズをニアレストネイバー法で実装してみました。
手法が単純すぎて精度はイマイチでしたので、もっと良い方法を試していきます。
ニアレストネイバー法は、着目点に一番近い位置にある色を使用するだけでした。
次のステップアップとしては、周辺1ピクセルを見て補間してみるのがよいでしょう。
そこでバイリニア法です。
2点をまっすぐ線形につなぐようにして補間する方法を、
線形補間(Linear Interpolation)と言います。縮めてLerpとも言います。
バイリニア(Bilinear)とは、縦と横の2(Bi)方向に対して線形(Linear)補間をすることを指します。
通常の線形補間は1方向の話なので簡単です。
基準となる2点を決めたら、比によって補間するだけです。
図を見れば、すぐわかると思います。
![]()
パラメータtを与えたら、t:1-tの比で補間することになります。
C = tA + (1 - t)B
t = 0なら始点Aに一致しますし、t = 1なら終点Bに一致します。
t = 0.5なら中点であり、AとBの相加平均となります。
バイリニア法は2方向に線形補間を適用することで、4点を補間します。
図の上では、何をしているのかは直感的にわかると思います。
![]()
これを数式にします。
E = aA + (1 - a)B
F = aC + (1 - a)D
G = bE + (1 - b)F
= abA + (1 - a)bB + a(1 - b)C + (1 - a)(1 - b)D
最終的な式を見ると、少し複雑になった気もしますが、
面積比で加重平均をとっていると解釈すれば直感的です。全体面積は1 x 1 = 1です。
理屈を理解したところで、早速実装に移りたいところですが、3点注意すべきことがあります。
①周辺ピクセルの選び方
着目点の周辺4ピクセルを選ぶわけですが、原画像と目的画像で解像度が異なるので、
どっち基準のスケールで選ぶのか、ということを考えないといけません。
拡大するとき、原画像のスケールで4ピクセルを選びます。これは素直。
縮小するとき、目的画像のスケールで4ピクセルを選びます。
目的画像の座標系で等距離にある4点をとり、
原画像の座標系に変換すると範囲が広がります(参照するピクセル数が増えます)。
広い範囲の情報を、狭い範囲の情報に集約するイメージと思えば、納得できるのではないでしょうか。
②領域外の扱い
周辺ピクセルを見るということは、原画像の領域外を参照することもあります。
そのため、領域外の扱いを決める必要があります。
バイリニアは補間計算しか定義しないので、このへんは実装次第です。
利用ケースに合わせて都合よくルールを決めておきましょう。
今回は原画像の範囲内に収まるよう座標を丸めることで、
最近傍点の色と同じとみなすようにします。
これで画像の縁に存在しない色が混ざることを回避します。
もし、リピートするテクスチャ素材を想定するなら、
領域外は反対側からの座標として丸めたほうが接続が自然になると考えられます。
他には鏡像(折り返し)扱いが考えられます。
画像を周期的に繰り返す信号としてみなすとき、鏡像は境界が連続するため、
離散フーリエ変換とかで周波数領域を見たときの形が良くなる、みたいな理論。
よくわからなくても、使えればいいので次いきましょう。
③完全透過色の扱い
アルファ値ゼロとなっているピクセルは完全透過色ですが、データとしてはカラー成分(RGB)を持ちます。
なので、補間処理でそのままピクセルのカラー成分に重みをかけて足してしまうと、
完全透過色であってもカラー成分が周囲に漏れてしまいます。
原画像では見えていなかった色が出現するので困ります。
今回は完全透過色のカラー成分はないものであってほしいので、
アルファ値ゼロならカラー成分の足し算をしないものとします。
結果として、完全透過色のカラー成分はすべてゼロ、つまり黒であるとみなすことと等価です。
但し、入力が既にこの条件を満たしているという前提で、今回のプログラムでは特に処理しません。
このように、完全透過色をどのように扱うかも実装次第です。
3点の注意点を確認したところで、実装例を示します。
バイリニア法で拡大・縮小した例を示します。
今回も弊社「魔法パスワード1111」のトルネードちゃんに登場してもらいます。
![]()
1.5倍
![]()
オリジナル
![]()
0.5倍
ニアレストネイバー法とも比較してみましょう。
![]()
1.5倍(ニアレストネイバー法)
![]()
1.5倍(バイリニア法)
![]()
0.5倍(ニアレストネイバー法)
![]()
0.5倍(バイリニア法)
かなりきれいになってきました。かわいい。
拡大はそこそこ良さそうですが、縮小はまだジャギが目立つ部分があります。
縮小目的ではまだ満足できないので、次回に続きます。
余談。
2次元が面積比で補間できるなら、3次元は体積比で補間できます。
これをトリリニア(Trilinear、トライリニア)法と言います。3(Tri)方向に対する線形(Linear)補間です。
トリリニア法は3次元空間を想定しますが、テクスチャフィルタリングにも使われます。
3番目の座標軸にミップマップレベルを採用することで、レベル間の補間を行うものです。
これまでに説明してきたニアレストネイバー法とバイリニア法も、
単純で比較的安価な処理なのでテクスチャフィルタリングでよく使われます。
この場合、ニアレストネイバー法はポイントフィルタリングと呼ばれることもあります。
言葉自体は知ってる人が多いと思いますが、何をやっているのか理解するとうまく使い分けできると思います。