超解像


リンク
画像の変換(目次ページ)
『拡大・縮小』関連
画像の縮小
画像の拡大「Nearest Neighbor法」
画像の拡大「Bilinear法」
画像の拡大「Bicubic法」
画像の拡大「Lanczos法」
画像の拡大-距離計算に関する考察
・超解像


東芝のホームページに REGZA に搭載している『超解像技術』
(レゾリューションプラスなど)の解説記事がありました。

ここここ


「実に、おもしろい。」
「私もやってみよう!」




ある画像①を拡大し、拡大した画像②をもう一度縮小③すると、
オリジナルとの差分④が得られます。



『差分が出てしまうということは、
 拡大時に落としてしまった情報成分があるのではないか?』


どうやら、そんな発想から来ているようです。

こういった考え方は MPEG Video エンコードのループバックに似ています。

『オリジナル画像①を拡大した②に情報の差分があるということは、』

『拡大という処理による予測にギャップ(予測誤差)があるという事で、』

『であれば、ギャップ(誤差)を補間してやれば良い。』


実にシンプルな(素直な)考え方で、
(シンプルだからこそ)「正しいんじゃないか?」という気がします。

ただ、東芝ホームページの情報からは
「どの様に補正すれば良いのか?」
がわかりませんでした。

「技術の核心部分はそう簡単に教えるわけがない。」
という事なのかもしれません。

そこで、手っ取り早く、
差分成分④を拡大したデータ⑤を作り、
拡大画像②に対して係数を掛けて足しこんでみる事にしました。



こうして作成した補正データ⑥に対して、もう一度縮小処理を行い、
それがオリジナル①に近くなるように、係数λを変えて調べてみました。

元画像 (160x120)

Bilinear 拡大 (240x180) Bilinear 拡大 (240x180)
+補正(λ=1.58)
Bilinear では(この画像では)λ=1.58 の時に最適になりました。
確かに絵を見ると、
補正前(←) はピンボケしているのに
補正後(→)はクッキリしているようです。
(効果はありそうです。)

Bilinear の場合、画像によって、あるいは拡大率によって
λ=0.5~2.0 ぐらいの間でバラツキがありました。

Bicubic 拡大 (240x180) Bicubic 拡大 (240x180)
+補正(λ=1.00)
Bicubic では、見た目に違いは、、、良くわかりません。
しかし、計測上では λ=1.0 の時に最適となり、
差分データはゼロではありませんから、
あきらかに補間前(←)と補間後(→)に差分があります。

Bicubic では λ=1.0 ~ 2.0 に収束する傾向がありました。
拡大率でλが 1.0 付近とか 1.5 付近と決まると、
画像を変えてもほぼ一定でした。

Lanczos2 拡大 (240x180) Lanczos2 拡大 (240x180)
+補正(λ=1.00)
Lanczos2 や Lanczos3 でも λ=1.0 ~ 2.0 に収束する傾向がありました。
画像に依存しない点も Bicubic と同様です。

補正前と補正後の画質の違いが良くわからない、という点も Bicubic と同様です。

Lanczos3 拡大 (240x180) Lanczos3 拡大 (240x180)
+補正(λ=1.00)
もしかすると、Bicubic や Lanczos2, Lanczos3 は周波数成分を
ある程度正確に処理できているので、
補正による効果は、ほとんど判らない程度、
という事なのかもしれません。


動画編集マニアの間では有名な AviUtl という編集ツールがあります。
そのプラグインを作ってみました。(拡大縮小と超解像のテスト)
置いておきます。
チューニングはしておりませんので『画質評価用』ということでお願いします。
(2009/07/12 追記)

AviUtl のプラグイン、チューニングしました。
ここに置いておきます。

| | コメント (0) | トラックバック (0)

アンチエイリアシングとClear Type


リンク
画像の変換(目次ページ)
アウトラインフォントとアンチエイリアシング
アウトラインフォント
・アンチエイリアシングと Clear Type

アンチエイリアシング

アンチエイリアシング(anti-aliasing)というのは、
上記のようなギザギザの線や曲線を下記のように滑らかにする事です。

この様にした方が、滑らかに見える、と言われています。

アンチエイリアシングの方法は幾つかあります。

1つは、実際に必要になる解像度よりも高い解像度でデータを作成し、
平均をとって中間値を作り出す方法です。

【高解像度データ】


【実際に表示されるデータ】


このように高解像度データから中間値を求めた方が奇麗に仕上がります。

しかし、この様に高解像度でデータを作るには、
そのためのメモリ領域と、高解像度にするための余計な処理時間が必要です。

そうではない場合、
つまり、表示の解像度までデータの解像度を落としてしまった場合は、
ぼかしフィルタを使ってぼかすだけになります。

【ぼかし】

ぼかしにはラプラシアン・フィルタなどが用いられます。

Clear Type

Clear Type については
アットマークの Clear Type 解説
や Microsoft msdn の Clear Type の概要
に詳しい解説がありますが、
一言で言うと、
『液晶の各画素の R,G,B の重心がずれているので、
 その重心ズレをも考慮してアンチエイリアスを掛ける』
という処理です。


具体的には、下記のようにモノクロデータがあったとすると、

従来方法は R,G,B に同じ値を設定するのに対し、
Clear Type は R,G,B ごとに補正した値を設定します。

フォントを表示した時に典型的な(白→黒→白)の場合には下記の様になり、
黒の左側は R が強調、右側は B が強調される事がわかります。

Clear Type を拡大した時にフォントの左側が赤っぽく、右側が青っぽい理由が
これでわかりましたね。


| | コメント (0) | トラックバック (0)

アウトラインフォント


リンク
画像の変換(目次ページ)
アウトラインフォントとアンチエイリアシング
・アウトラインフォント
アンチエイリアシングと Clear Type

アウトラインフォントには「2次 B-スプライン曲線」や「ベジェ曲線」と
呼ばれるものを使います。

実は、
・2次ベジェ曲線 (Quadratic Bezier Curve)
・2次 B-スプライン曲線 (Quadratic B-Spline Curve)
の2つは同じものです。

・2次ベジェ曲線 (Quadratic Bezier Curve)
・3次ベジェ曲線 (Cubic Bezier Curve)
の2つは次数が違いますが考え方は同じです。

PostScriptフォント3次ベジェ曲線 (Cubic Bezier Curve)
True Typeフォント2次ベジェ曲線 (Quadratic Bezier Curve)
(2次 B-スプライン曲線 ( Quadratic B-Spline Curve) )

2次ベジェ曲線

下記のように3点(Q1,Q2,Q3)が与えられたとします。
Q1F1:F1Q2 = 1:(1-t) となるように点 F1 を定めます。
同様に、点 F2 と G1 を定めます。
0≦t≦1 の範囲で t を動かすと G1 の軌跡がカーブを描きます。
このカーブを 2次ベジェ曲線と呼びます。


このカーブを直観的に理解するには、
(英語版 Wiki)のモーションGIF が秀逸です。

2次ベジェ曲線の数式による定義
次の2次多項式で与えられます。
P = (1-t)2*Q1 + 2t(1-t)*Q2 + t2*Q3
(0≦t≦1)

2次ベジェ曲線への再帰的アプローチ
実は、
上記の数式を用いてコンピュータで曲線の座標をプロットしていくことは
簡単です。
しかしながら、プロットした点を隙間の無い連続した線にするのは
コンピュータにとってはちょっと大変なのです。

フォントの展開では別の手法を取ります。
同じ事を繰り返す事を『再帰(さいき)』と呼びますが、
再帰という方法でベジェ曲線を引く方法です。


まず、Q1 と Q2 の中間点(まん中の点) R1 を求めます。
同様に R2 を求めます。

次に R1 と R2 の中間点 S1 を求めます。

Q1-R1-S1 の3点に対して
Q1-Q2-Q3 でやった事と同じ事を繰り返します。

これを何回か繰り返すと、ある曲線に収束していく事がわかります。
通常は数回で収束します。

この曲線は、フォントデータでは縁取り(境界線)になる部分です。

フォントでは、目で見て区別が付かない程度に収束すればよいので、
たとえば Q2 と S1 の距離が 1 ピクセル以下になれば、
再帰を中止して、あとは、その3点を線で結べば完成です。

最後に得られた曲線の内側を、べったりと塗りつぶします。
(この塗りつぶしの際に、線に隙間が無い方が都合が良いのです。)
こうしてフォントの完成です。

2次ベジェ曲線では次のような特徴があります。
・端点 Q1 におけるカーブの傾きは Q2 を向いている。
・端点 Q3 におけるカーブの傾きは Q2 を向いている。
・Q1、Q3 の中間点を A1 とすると
 A1S1:S1Q2 = 1:1 となる。
 (A1 と Q2 の中間点 S1 にカーブが接する)


3次ベジェ曲線
考え方は 2次ベジェ曲線と同じです。(点を増やしただけ)

下記の図で
0≦t≦1 の範囲で t を動かすと H1 が曲線を描きます。
この軌跡が 3次ベジェ曲線です。


3次ベジェ曲線の数式による定義
次の3次多項式で与えられます。
P = (1-t)3*Q1 + 3t(1-t)2*Q2 + 3t2(1-t)*Q3 + t3*Q4
(0≦t≦1)


3次ベジェ曲線への再帰的アプローチ
Q1, Q2, Q3, Q4 の中点 R1, R2, R3
R1, R2, R3 の中点 S1, S2
S1, S2 の中点 T1 を求めます。

Q1-R1-S1-T1 の4点が得られます。

この4点に対して、Q1-Q2-Q3-Q4 の4点と同じ事をします。

2次ベジェ曲線の時と同様に、これを数回繰り返すと曲線に収束します。

フォントの場合はこの内側を塗りつぶします。


3次ベジェ曲線では次のような特徴があります。
・端点 Q1 におけるカーブの傾きは Q2 を向いている。
・端点 Q4 におけるカーブの傾きは Q3 を向いている。
・Q1、Q4 の中間点を A1 とすると
 A1T1:T1R2 = 3:1 となる。  (T1 にカーブが接する)


アウトラインフォント
ベジェ曲線の基点となる点(上記の Q1~Q4(or Q3) )
でデータが構成されています。

ドローソフト(Adobe の Illustrator とか MS Office の power point とか)で
下記のような曲線を描く事ができます。

アンカーポイント(曲線上の制御点)と方向線の制御点が 3次ベジェの端点に
なっているようです。

この様なカーブでフォントの境界線が作れるであろう事は想像がつくかと思います。

パソコンなんかでフォント1文字を表示するたびに、
ベジェ曲線の展開と塗りつぶしを行っているわけです。
(もちろん、よく使う文字は高速化のため作り置きしていると思いますが。)

ビットマップフォントに比べたアウトラインフォントの利点ですが、
このように基点によってデータを管理する事によって
【元データ】から


フォントの【拡大】


【伸ばし】


【回転】


【傾け】

などが自在にできるわけです。

(注)通常のフォントはイタリック用のフォントを別データとして持っていたはずです。
 (上記のように基点を傾けてその都度作成しているわけではありません。)

| | コメント (0) | トラックバック (0)

エッジ検出・エッジ強調・ぼかし


リンク
画像の変換(目次ページ)

【エッジ検出】
まず、エッジ検出の考え方ですが、
以下のように隣のピクセル値との差分を取る事が基本的な考え方です。

実際には、画像は2次元なので、
上下左右のピクセルとの差分を取るために次のようなフィルタを用います。
0-10
-14-1
0-10

0-10
-14-1
0-10
=
0-10
010
000
+
000
-110
000
+
000
01-1
000
+
000
010
0-10
   上との差分  左との差分  右との差分  下との差分


これとは別に次のようなフィルタを用いる場合もあります。
(斜め方向のエッジも検出できるフィルタです。)
-1-1-1
-18-1
-1-1-1

-1-2-1
-212-2
-1-2-1


上の絵(↑)のエッジ検出したものが下記(↓)です。

(エッジの方向によって色を付けています。)


【シャープネス(エッジ強調)】
エッジ強調には次のようなフィルタを用います。
0-10
-110-1
0-10
このフィルタの意味ですが、
上下左右の 3x3 ピクセルの値が下記であったとします。
P-1,-1P-1,0P-1,1
P0,-1P0,0P0,1
P1,-1P1,0P1,1
各ピクセルにフィルタ係数を掛けて得られる次の値がエッジ強調後の値です。
(10*P0,0 - P-1,0 - P0,-1 - P0,1 - P1,0) / (10-1-1-1-1)


エッジ強調には、これとは別のフィルタが用いられる場合もあります。
たとえば下記。
-1-1-1
-110-1
-1-1-1

-2-2-2
-232-2
-2-2-2


実際に、やってみましょう。
[エッジ強調前](元データ)

上(↑)のエッジ検出がこれ(↓)です。


[エッジ強調1-1]
0-10
-110-1
0-10


ほんの少し、エッジが強調されています。

フィルタ係数を少し変えてみましょう。
[エッジ強調1-2]
0-20
-210-2
0-20


前よりもクッキリしました。

もう少しフィルタ係数を変えてみましょう。
[エッジ強調1-3]
0-2.20
-2.210-2.2
0-2.20


だんだん鮮明になってくる気がします。

もう少し変えてみましょうか。
[エッジ強調1-4]
0-2.40
-2.410-2.4
0-2.40


ここまでやると、やり過ぎな感じです。
人為的な修正部分が目立ち過ぎて、自然さが失われたようです。
本来なら目立たないはずのノイズが強調によって目立ってしまい、
そのような不自然さを感じるのかもしれません。

念のため、もう少しフィルタ係数を変えてみましょうか。
[エッジ強調1-5]
0-2.50
-2.510-2.5
0-2.50


これはもう、『エッジ強調』というより『エッジそのもの』です。
というのは、次の式が成り立ちます。
0-2.50
-2.510-2.5
0-2.50
=
0-10
-14-1
0-10
* 2.5
右側のフィルタ係数をみると、これは『エッジ検出フィルタ』の係数です。

ここまでの「フィルタ係数の微調整」をまとめると、こんな感じになります。
[エッジ強調1-1]エッジ成分が少ない
[エッジ強調1-2]
[エッジ強調1-3]
[エッジ強調1-4]エッジ成分が多い
[エッジ強調1-5]エッジ成分そのもの
つまり、フィルタ係数を微調整する事で、
「オリジナル画像とエッジ成分の比率を変えている」
わけですね。
そして、エッジ成分の比率を上げるとエッジが協調される、と。


別のフィルタ係数でも同じ事をやってみましょう。
[エッジ強調2-1]
-2-3-2
-332-3
-2-3-2



[エッジ強調2-2]
-2-5-2
-532-5
-2-5-2



[エッジ強調2-3]
-2-5.5-2
-5.532-5.5
-2-5.5-2



[エッジ強調2-4]
-2-6-2
-632-6
-2-6-2




【ぼかし】
『エッジ強調』は「オリジナル画像」に「エッジ成分」を加える事でした。
『ぼかし』の場合は、逆の事をすれば良いわけです。
たとえば、次のようなフィルタが用いられます。
111
151
111

フィルタというのは何も 3x3 に限ったわけではなく、
次のような 5x5 が用いられる場合もあります。
11111
10001
10001
10001
11111

| | コメント (0) | トラックバック (0)

画像の拡大-距離計算に関する考察


リンク
画像の変換(目次ページ)
『拡大・縮小』関連
画像の縮小
画像の拡大「Nearest Neighbor法」
画像の拡大「Bilinear法」
画像の拡大「Bicubic法」
画像の拡大「Lanczos法」
・画像の拡大-距離計算に関する考察
超解像
ここまで、Bilinear法、Bicubic法、Lanczos法、すべて
「X方向の距離とY方向の距離を求め、それぞれのウェイト計算をし、
 X方向のウェイトとY方向のウェイトを掛ける。」
という手法をとってきました。


しかし、距離と言えば、X方向やY方向ではなく直線距離のはず。
つまり、デジカメであれば、カメラを傾ける事でX軸Y軸は傾くし、
スキャナーだって対象の角度を変えれば傾く。

X軸やY軸の方向は、人間が処理の都合で後から付けたもの。

画像の拡大にとって、
「そのような後付けの軸方向に左右されるべきものなのだろうか。」


「直線距離で計算するのが正しいのでは?」


そんな素朴な疑問がわいてきました。

では、実際に試して確認してみましょう。

用いたのは3つのテストデータ。
テストデータ1
(弱エッジ)
緩やかに変化するグラデーションデータ
テストデータ2
(強エッジ)
白黒パターン
テストデータ3
(ワイングラス)
実写データ


テストデータ1
(弱エッジ)
128x128 → 240x320

まず最初に用いたのはこの同心円状のデータ。
何かのテストチャート、という訳ではなく、
私が適当に作ったデータです。

左下を中心にして、白黒レベルが波のようになっています。
右上部の波が密になった場所で灰色の楕円が幾つか見えますが、
これは、各ピクセルの形が四角形なため、副二次的に発生したモアレです。
左上隅と右下隅にも同様の傾向が見られます。

Nearest Neighbor
『Nearest Neighbor法』は「ウェイト」という考え方はありません。
ここでは、比較のために載せています。

Bilinear
weight = weight_x * weight_y
weight_x = bilinear_weight( dx )
weight_y = bilinear_weight( dy )
Bilinear
weight = bilinear_weight( d )
d = √( dx2 + dy2 )
左側(←)は、X方向、Y方向それぞれのウェイトを掛ける従来の方法。
右側(→)は、直線距離でウェイトを求める方法です。
「Bilinear法」は参照ピクセルが 2x2 ピクセルなので、
その程度では、ほとんど差が出ません。

Bicubic
weight = weight_x * weight_y
weight_x = bicubic_weight( dx )
weight_y = bicubic_weight( dy )
Bicubic
weight = bicubic_weight( d )
d = √( dx2 + dy2 )
左側に比べ、右側がくっきりしている事がわかります。
「シャープネス・フィルタがより強く掛かっている」という認識で良いと思います。
しかし、右側の画像のグラデーション部分(左下4分の1の領域)を見ると
四角いブロック状のノイズ(モザイク・ノイズ)が出ている事が分かります。

その点に注意して左側の同じ位置を(じっくり)見ると、
うっすらとですが、ブロック状のノイズが出ている事が分かります。

Lanczos2
weight = weight_x * weight_y
weight_x = lanczos_weight( dx, 2 )
weight_y = lanczos_weight( dy, 2 )
Lanczos2
weight = lanczos_weight( d, 2 )
d = √( dx2 + dy2 )
右側の画像の中央部分のシマシマを見ると、左側よりもくっきりしているようです。
Lanczos2 に関しては、直線距離で行った方がシャープネス・フィルタが掛かる
と言ってよいでしょう。

Lanczos3
weight = weight_x * weight_y
weight_x = lanczos_weight( dx, 3 )
weight_y = lanczos_weight( dy, 3 )
Lanczos3
weight = lanczos_weight( d, 3 )
d = √( dx2 + dy2 )
中央部分のシマシマを見ると、左側よりも右側の方がくっきりしています。
同じく中央部分の、同心円のカーブの滑らか具合を Lanczos2、Lanczos3 で比較
すると、Lanczos3 の方が優れているようです。



次に、別のパターンで拡大方法の違いを見てみましょう。
テストデータ2
(強エッジ)
64x32 → 180x120

このパターンはエッジが強い画像(輝度が白→黒とレベル差が大きい画像)です。

Nearest Neighbor
「Nearest Neighbor 法」はエッジのレベル差は維持されているものの、
中央部分の細いシマシマを見ると、線の幅が不正確である事がわかります。

Bilinear
weight = weight_x * weight_y
weight_x = bilinear_weight( dx )
weight_y = bilinear_weight( dy )
Bilinear
weight = bilinear_weight( d )
d = √( dx2 + dy2 )
「Bilinear 法」は左側、右側、あまり差が無く、
どちらもボケている事が分かります。
(よくよく見ると、右側にノイズが出ています。)

Bicubic
weight = weight_x * weight_y
weight_x = bicubic_weight( dx )
weight_y = bicubic_weight( dy )
Bicubic
weight = bicubic_weight( d )
d = √( dx2 + dy2 )
「Bicubic 法」は左側よりも右側の方がくっきりしています。
しかし、白の四隅、黒の四隅で形が崩れている事がわかります。

Lanczos2
weight = weight_x * weight_y
weight_x = lanczos_weight( dx, 2 )
weight_y = lanczos_weight( dy, 2 )
Lanczos2
weight = lanczos_weight( d, 2 )
d = √( dx2 + dy2 )
「Lanczos2」は左側より右側がくっきりしています。

Lanczos3
weight = weight_x * weight_y
weight_x = lanczos_weight( dx, 3 )
weight_y = lanczos_weight( dy, 3 )
Lanczos3
weight = lanczos_weight( d, 3 )
d = √( dx2 + dy2 )
「Lanczos3」の右側はエッジの反射(折り返し)がノイズとなって出ています。
それを踏まえて左側を見ると、同じ位置にうっすらとノイズが分かります。



次に実写で違いを見てみましょう。
テストデータ3
(ワイングラス)
160x120 → 384x256 (下記の拡大結果は一部を切り出し)

Nearest Neighbor
「Nearest Neighbor」はブロック状(モザイク状)になります。

Bilinear
weight = weight_x * weight_y
weight_x = bilinear_weight( dx )
weight_y = bilinear_weight( dy )
Bilinear
weight = bilinear_weight( d )
d = √( dx2 + dy2 )
「Bilinear」では、左側、右側で大した違いはありません。

Bicubic
weight = weight_x * weight_y
weight_x = bicubic_weight( dx )
weight_y = bicubic_weight( dy )
Bicubic
weight = bicubic_weight( d )
d = √( dx2 + dy2 )
「Bicubic」では右側がくっきりしています。
しかし、グラスにうつった照明の反射(水面と縁の間)を見ると、
グラデーション部分にブロックノイズが出ている事が分かります。
シャープネス・フィルタ特性が強すぎるのではないかと思います。

Lanczos2
weight = weight_x * weight_y
weight_x = lanczos_weight( dx, 2 )
weight_y = lanczos_weight( dy, 2 )
Lanczos2
weight = lanczos_weight( d, 2 )
d = √( dx2 + dy2 )
「Lanczos2」右側の方がくっきりしています。

Lanczos3
weight = weight_x * weight_y
weight_x = lanczos_weight( dx, 3 )
weight_y = lanczos_weight( dy, 3 )
Lanczos3
weight = lanczos_weight( d, 3 )
d = √( dx2 + dy2 )
「Lanczos3」右側の方がくっきりしています。


このワイングラス、グラスの側面にブドウの模様がほどこされています。
拡大後、この模様がちゃんと出ているのは Bicubic, Lanczos2, Lanczos3 の右側
でしょう。

総合的に判断すると、
画質という意味では Lanczos2 の右側(直線距離で計算)が最もバランスが
とれているように思います。

ただし、Lanczos2 を直線距離で処理すると、
出力側の各ピクセルに対して 16 ピクセルを参照するため、
1ピクセルあたり、平方根(√)の計算が 16 回発生する事になり、
計算量がとんでもない事になります。


【まとめ】
  ( X方向ウェイト)*( Y方向ウェイト) (直線距離ウェイト)
Bilinear ぼける ←と大差なし
ぼける
Bicubic ぼける 画質は改善
×グラデーションにブロックノイズ
×処理が重い
(√計算 16回 / pixel)
Lanczos2 ぼける 画質は改善
(バランスがとれている)
×処理が重い
(√計算 16回 / pixel)
Lanczos3 ぼける 画質は改善
×エッジ部分で折り返し
×処理が重い
(√計算 36回 / pixel)

| | コメント (0) | トラックバック (0)

画像の拡大「Lanczos法」


リンク
画像の変換(目次ページ)
『拡大・縮小』関連
画像の縮小
画像の拡大「Nearest Neighbor法」
画像の拡大「Bilinear法」
画像の拡大「Bicubic法」
・画像の拡大「Lanczos法」
画像の拡大-距離計算に関する考察
超解像
【Lanczos 法】
Lanczos 法ではバイキュービック法とは異なる特性のフィルタを使います。

lanczos_weight( d, n ) =   sinc( d ) * sinc( d / n )  ( | d | ≦ n )
0( other )

sinc( x ) = sin( x * π ) / ( x * π )

この式で、
n = 2 が Lanczos2,
n = 3 が Lanczos3 です。

Lanczos2 は距離が2以内の画素、つまり4x4画素を参照して
拡大後の各ピクセル値を求めます。


Lanczos3 は距離が3以内、つまり6x6画素を参照します。


単純に考えると、4x4 = 16, 6x6=36 ですから、
Lanczos3 は Lanczos2 の2倍以上の計算量が必要な事になります。
(処理時間が倍、という事と思ってよいでしょう。)


では、4x4 の代わりに 6x6 を用いるメリットは何でしょうか?

「4x4 の外側の画素の影響を受ける」という事ですね。

下記に Lanczos2 と Lanczos3 で拡大した画像を作ってみました。
違いが分かりますか?

(160x120 → 384x256)と拡大
《元画像データ》

《Lanczos2》


《Lanczos3》




まっすぐな線(縦、横、斜め、どれでも)というのは、
4x4 であっても、6x6 であっても大差無い結果が得られます。

4x4 と 6x6 の違いは、丸みのあるカーブの部分で差が出ます。

上記の Lanczos2, Lanczos3 の画像で、
グラスの縁の楕円形のカーブに着目してみてください。

Lanczos3 の方が、より滑らかになっているのが分かると思います。

しかし逆に言えば、「その違いを意識して凝視しないと分からないレベル」
という事なのかもしれません。


もし、2つの違いを感じた方がいたとすれば、
つまり、
「片方のグラスがクリスタルグラスっぽい」とか、
「プラスチックぽい」とか、
あるいは、
「どちらかの白ワインがより本物っぽい」とか、
そういう感じがした人は、
その感覚は貴重なのかもしれません。

というのは、人間の漠然とした知覚というものは、
意外と細かな違いを的確にとらえている事があるらしいからです。

| | コメント (3) | トラックバック (0)

画像の拡大「Bicubic法」


リンク
画像の変換(目次ページ)
『拡大・縮小』関連
画像の縮小
画像の拡大「Nearest Neighbor法」
画像の拡大「Bilinear法」
・画像の拡大「Bicubic法」
画像の拡大「Lanczos法」
画像の拡大-距離計算に関する考察
超解像
【バイキュービック法 (Bicubic 法)】
バイリニア法は隣接する4点から線形的に中間値を求めているだけなので、
エッジが立っている場所でのガタガタ感が否めません。
バイキュービック法
もう少し滑らかに中間値を求めてやればいいんじゃね?
という発想からきているのだと思います。

そのためには隣接する点だけではなく、その先の点をも考慮する必要があります。
つまり、d6, d7 の値を決めるために
バイリニア法 では s2, s3 の値を参照しました。
それよりも滑らかにしようと思うと、
s2, s3 に加え、s1, s4 の値も参照する必要があります。

下図で言うと赤い点のまわりの2x2点を一回り大きくして
4x4の青い点を参照し、そこから中間値を求めます。


計算方法は次の通りです。
まず、x方向の距離(dx1~dx4)とy方向の距離(dy1~dy4)を求めます。


次に縦方向、横方向それぞれの重みづけ(=ウェイト,weight)を求めます。
(wx1~wx4, wy1~wy4)


バイキュービック法でのウェイト計算式は次の通りです。
bicubic_weight( d ) =   1 - 2*d2 + d3(d ≦ 1.0 )
4 - 8*d + 5*d2 - d3  (1.0 ≦ d ≦ 2.0 )
0(d ≧ 2.0 )

たとえば d = 0.1 の場合は
bicubic_weight( 0.1 ) = 1 - 2*0.12 + 0.13 = 0.981

式に3乗が含まれているので Cubic (キュービック) と言うらしいです。

このウェイト式はグラフで表すと下記のようになります。

このようにしてウェイト値(wx1~wx4, wy1~wy4)が求まったら、
4x4の各点に対して
(ピクセル値) * wx * wy
を計算して、それを合計します。
この合計値をウェイトの合計値で割ったものが求める中間値です。

(求める中間値) =
4 4 4 4
Σ Σ ((ピクセルm,k値)* wxm * wyk)/ Σ Σ (wxm * wyk
m=1 k=1 m=1 k=1

(160x120 → 384x256)
《元画像データ》

《Bicubic》


同様の考え方をすれば、「Nearest Neighbor 法」や「バイリニア法」も
ウェイトの考え方ができます。

Nearest Neighbor 法のウェイト計算式。
nearest_neighbor_weight( d ) =   1  (d ≦ 0.5 )
0( other )

バイリニア法のウェイト計算式。
bilinear_weight( d ) =   1 - d  (d ≦ 1.0 )
0( other )


「一種のフィルタ」と考える事ができますね。
フィルタを変える事でギザギザが無くなったり、滑らかになったりします。
「スムーズ・フィルタ」「エッジ強調フィルタ」と思ってよいかもしれません。

| | コメント (18) | トラックバック (0)

画像の拡大「Bilinear法」


リンク
画像の変換(目次ページ)
『拡大・縮小』関連
画像の縮小
画像の拡大「Nearest Neighbor法」
・画像の拡大「Bilinear法」
画像の拡大「Bicubic法」
画像の拡大「Lanczos法」
画像の拡大-距離計算に関する考察
超解像
【線形補間法、バイリニア法 (Bilinear 法)】
下の図で、縦軸はピクセルの画素値です。
たとえば、24bit RGB の場合、R,G,B それぞれ 0~255 の値をとりますが、
その 0~255 が縦軸だと思ってください。
横軸は隣り合うピクセルです。

この図は、たまたま拡大率が3倍の場合を示しています。
この場合には、
 s1 → d2
 s2 → d5
 s3 → d6
のように、3ピクセルおきに、そのままの値を持ってくれば良いです。
その間にある、d3, d4 は s1 と s2 の間の値(中間値)を持ってくれば
綺麗な映像になりそうな気がします。
この場合には、
 d3 = (2*s1 + s2) / 3
 d4 = (s1 + 2*s2) / 3

バイリニア法の考え方としては
中間の値を持ってくればいいんじゃね?
です。

元画像と拡大画像の写像を考えると、
拡大側の各点に対して、逆写像の点があります。
その逆写像の点(下図の左側の赤い点)の周りには、
元画像の4点(青い点)があります。

この4点の比率をとってやれば中間値が求まります。


この方法によって得られた拡大画像です。
(160x120 → 384x256)
《元画像データ》

《Bilinear》


| | コメント (0) | トラックバック (0)

画像の拡大「Nearest Neighbor法」


リンク
画像の変換(目次ページ)
『拡大・縮小』関連
画像の縮小
・画像の拡大「Nearest Neighbor法」
画像の拡大「Bilinear法」
画像の拡大「Bicubic法」
画像の拡大「Lanczos法」
画像の拡大-距離計算に関する考察
超解像
【画像の拡大】
画像の拡大には幾つかの方法があります。

まずは、最短距離法(Nearest Neighbor 法)から。
画像の拡大を、「元画像から出力画像への写像」と考える事ができます。
出力対象の各点 (dx,dy) に対して逆写像の点 (sx,sy) が計算できます。

やっかいなのは、この各点 (sx,sy) は実数(連続した値)で計算できますが、
実際の元画像はピクセル単位の飛び飛びな値(離散値)だという事です。
最短距離法(Nearest Neighbor 法)
逆写像の点に最も近い1ピクセルを持ってくる
という方法です。

試しに次の絵を拡大してみましょう。
《元画像データ》

160x120 の大きさです。
これを 384x256 にしてみましょう。
縦に 2.13 倍、横に 2.4 倍です。
(比率を変える事で何か影響があるかもしれないので、
わざと縦横比率を変えています。)

《Nearest Neighbor》


Nearest Neighbor 法は、
元画像の各ピクセルを単純に引き延ばしているだけなので、
各ピクセルは四角い形に拡大され、
全体の絵は、それらのブロックが貼りあわされたモザイク状になります。

| | コメント (0) | トラックバック (0)

画像の拡大・縮小


リンク
画像の変換(目次ページ)
『拡大・縮小』関連
・画像の縮小
画像の拡大「Nearest Neighbor法」
画像の拡大「Bilinear法」
画像の拡大「Bicubic法」
画像の拡大「Lanczos法」
画像の拡大-距離計算に関する考察
超解像
【画像の縮小】
たとえば、ある画像を縦横それぞれ3分の1にする事を考えてみましょう。
元画像の 3x3 ピクセルを 1 ピクセルにすれば良いのですが、
代表点をもってくる方法(たとえば中央の1点)と
3x3 ピクセルの平均を取る方法があります。

画質にこだわるのであれば平均を取った方が奇麗です。


画像を縮小する場合、比率がちょうど整数分の1になるとは限りません。
そのような場合、境界部分を比率で割って平均を出す事になります。

| | コメント (0) | トラックバック (0)