ImageLab

処理解説 ← ImageLab を開く 使い方
ImageLab に入っている22の処理について、原理・式・見どころをまとめたものです。
アプリの右側に出る「解説」と同じ文章なので、触りながら読むなら、アプリを開いたままそちらを見るほうが早いです。 このページは、通して読みたいときや、あとから探したいときのためのものです。

生成日:2026-09-10(node docs/_gen_docs.jsjs/ops/*.js から自動生成)

基本

原画(処理なし)

原理

何も加工せずそのまま表示します。読み込んだ画像の素性(ヒストグラムの形、ノイズの量、白飛び・黒つぶれの有無)を確認するための状態です。

g(x, y) = f(x, y)

注意点・見どころ

▲ 目次へ戻る

点処理

トーンカーブ

パラメータ

名前種類既定値範囲・選択肢
カーブ(点をドラッグ/空白をクリックで追加/右クリックで削除)curve[[0,0],[255,255]]制御点をドラッグして編集
対象selectluma輝度のみ(色比を保つ) / RGB個別

原理

入力の明るさ 0〜255 を、出力の明るさ 0〜255 へ写す「対応表(LUT)」を手で描く処理です。カーブが対角線より上にある区間は明るく、下にある区間は暗くなり、傾きが急な区間ほどコントラストが強くなります。周りの画素を一切見ないので、これは点処理の代表例です。

たとえるなら、音量つまみを「小さい音・普通の音・大きい音」で別々に設定できるイコライザです。全体の音量を上げるのではなく、どの音量帯をどれだけ持ち上げるかを決めます。

g(x, y) = T( f(x, y) )   T は 0..255 → 0..255 の単調写像
LUT を1本作れば、あとは全画素で表引きするだけ(O(N)、画像サイズに比例)

注意点・見どころ

▲ 目次へ戻る

ガンマ補正

パラメータ

名前種類既定値範囲・選択肢
γrange10.1 〜 3(刻み 0.01)
対象selectluma輝度のみ(色比を保つ) / RGB個別

原理

明るさをべき乗で写し替える処理です。0〜1 に正規化した値を 1/γ 乗するので、γ を大きくすると暗部が大きく持ち上がり、明部はあまり動きません。人間の目は暗い側の差に敏感なので、この「暗部を厚く配分する」性質が理にかなっています。

たとえるなら、階段の段差を一律に下げるのではなく、下の方の段だけ細かく刻み直すようなものです。踏み外しやすい足元だけ丁寧にする、という配分の変更です。

g = 255 · ( f / 255 ) ^ (1/γ)
γ > 1 … 明るく(暗部が伸びる) / γ < 1 … 暗く / γ = 1 … 恒等
※ ソフトによっては指数を γ と書く流儀もあります。向きが逆になるので注意。

注意点・見どころ

▲ 目次へ戻る

ヒストグラム平坦化

パラメータ

名前種類既定値範囲・選択肢
対象selectluma輝度のみ(色比を保つ) / RGB個別
強さrange10 〜 1(刻み 0.01)

原理

画像全体のヒストグラムを見て、累積度数がまっすぐな直線になるように明るさを割り当て直す処理です。画素の多い明度帯には広い出力範囲を、画素の少ない明度帯には狭い出力範囲を配ります。結果として、混み合っていた階調が引き伸ばされてコントラストが立ちます。

たとえるなら、席の埋まり方に合わせて座席の幅を配り直すことです。満員の車両は幅を広げ、がらがらの車両は詰める。合計の長さは変えずに、混雑を均します。

g = round( 255 · ( CDF(f) − CDF_min ) / ( N − CDF_min ) )
CDF(v) = Σ_{k ≤ v} hist(k)、N は総画素数

注意点・見どころ

▲ 目次へ戻る

CLAHE(適応的平坦化)

パラメータ

名前種類既定値範囲・選択肢
タイル分割数(縦横)range82 〜 16(刻み 1)
クリップ上限range2.51 〜 10(刻み 0.1)
強さrange10 〜 1(刻み 0.01)

原理

画像をタイルに切り、タイルごとにヒストグラム平坦化をかけます。ただし度数に上限(クリップ)を設け、あふれたぶんを全階調に配り直してから累積を取ります。これで「平坦な部分のノイズだけが極端に持ち上がる」という適応的平坦化の副作用を抑えます。タイルの継ぎ目は、近い4タイルの写像を双線形で混ぜて消します。

たとえるなら、全国一律のテストの偏差値ではなく、クラスごとに評価をつけ直すやり方です。ただし1人だけ突出しても評価が振り切れないよう上限を設け、クラスの境目では隣のクラスの基準と混ぜてなだらかにつなぎます。

タイル (i, j) の写像 M_ij(v) = 255 · CDF_clip( v )
g(x, y) = 双線形補間( M_i0j0, M_i1j0, M_i0j1, M_i1j1 )( f(x, y) )
クリップ上限 = clip × (タイル画素数 / 256)

注意点・見どころ

▲ 目次へ戻る

空間フィルタ

平均化 / ガウシアン

パラメータ

名前種類既定値範囲・選択肢
種類selectgaussガウシアン / 平均化(ボックス)
σ(標準偏差)range20.3 〜 12(刻み 0.1)
窓の半径range31 〜 20(刻み 1)

原理

注目画素の周りを重み付きで平均する処理です。平均化は窓の中を一律の重みで、ガウシアンは中心が重く外へ行くほど軽い釣鐘型の重みで平均します。どちらも高い周波数(細かい変化)を削るローパスフィルタです。

たとえるなら、アンケートの回答を近所どうしで持ち寄って平均を取るようなものです。平均化は「半径◯m 以内の人を全員同じ1票」で数え、ガウシアンは「近い人ほど重く数える」やり方です。後者のほうが、境界での不自然な切れ方が起きません。

ガウシアン:G(x, y) = (1 / 2πσ²) · exp( −(x² + y²) / 2σ² )
分離可能:G(x, y) = G(x) · G(y) なので、横1回 → 縦1回で済む
計算量:素朴に2次元でやると O(N·k²)、分離すると O(N·2k)

注意点・見どころ

▲ 目次へ戻る

メディアン

パラメータ

名前種類既定値範囲・選択肢
窓の半径range11 〜 5(刻み 1)
反復回数range11 〜 3(刻み 1)

原理

窓の中の画素を値の順に並べ、真ん中の値を採用します。平均と違って「足し算をしない」のが要点で、窓の中に極端な値が混ざっても、それが順位の端にいる限り結果に影響しません。線形フィルタではないため、重ね合わせも分離もできません。

たとえるなら、審査員の点数から最高点と最低点を捨てて中央の評価を採るやり方です。1人が0点をつけても、平均と違って結果はほとんど動きません。

g(x, y) = median{ f(x+i, y+j) : |i| ≤ r, |j| ≤ r }
計算量:窓 k×k で素朴に O(N·k² log k)。窓が大きいときはヒストグラムを使った O(N·k) 実装が定石

注意点・見どころ

▲ 目次へ戻る

バイラテラル

パラメータ

名前種類既定値範囲・選択肢
σ_space(距離)range30.5 〜 8(刻み 0.1)
σ_color(値の差)range302 〜 100(刻み 1)
値の差の測り方selectluma輝度差(色ずれが出にくい) / RGB のユークリッド距離

原理

ガウシアン平滑化の重みに、もう一つ「値がどれだけ違うか」の重みを掛けます。近くにあっても値が大きく違う画素(=エッジの向こう側)はほとんど平均に参加しません。結果として、平坦な部分のノイズだけが消え、エッジは立ったまま残ります。

たとえるなら、近所の人の意見を聞くときに「距離が近い人」だけでなく「自分と意見が近い人」の声を重く採る合議です。道の向こう側の反対意見に引きずられないので、立場の境目がぼやけません。

g(p) = (1/W) Σ_q f(q) · exp( −‖p−q‖² / 2σ_s² ) · exp( −|f(p)−f(q)|² / 2σ_c² )
W = Σ_q (同じ2つの重みの積)
重みが画素ごとに変わるので線形ではなく、分離もできない → O(N·k²) が基本

注意点・見どころ

▲ 目次へ戻る

アンシャープマスク

パラメータ

名前種類既定値範囲・選択肢
range10 〜 3(刻み 0.05)
半径 σrange1.60.3 〜 10(刻み 0.1)
しきい値range00 〜 60(刻み 1)
差分マスクを表示(何を足しているか)checkboxfalseオン / オフ

原理

元画像から、ぼかした画像を引きます。残るのは「ぼかしで失われた成分」=細部だけで、これを元画像に足し戻すと細部が強調されます。名前は「ぼけていないマスク」ではなく、暗室でぼかしたネガをマスクに使った古典的な手法に由来します。

たとえるなら、写真から「大づかみな明暗」だけを取り除いて細かい模様を取り出し、それを元の写真に重ね刷りするようなものです。

mask = f − Gσ * f
g = f + amount · mask   (|mask| ≤ threshold の画素は mask = 0 とする)
= (1 + a)·f − a·(Gσ * f) なので、正味は「ハイパスを足す」ことと同じ

注意点・見どころ

▲ 目次へ戻る

周波数領域

FFT スペクトル

パラメータ

名前種類既定値範囲・選択肢
表示selectpower対数パワースペクトル / 位相(色相=角度/明るさ=強さ) / 振幅だけで再構成(位相を捨てる) / 位相だけで再構成(振幅を一定に)
対数の効きrange30 〜 6(刻み 0.1)
境界処理(2の冪への埋め方)selectreflect鏡映で埋める(既定) / ゼロで埋める(十字が出ます) / Hann 窓を掛ける(十字が消えます)
周波数の目盛りを重ねるcheckboxtrueオン / オフ

原理

画像を「いろいろな細かさの縞模様の重ね合わせ」として書き直したものが、2次元フーリエ変換です。出てくるスペクトルは、中央が DC(画像全体の明るさ)、中央から離れるほど細かい縞に対応します。輝点の位置がその縞の向きと細かさを、明るさがその縞がどれだけ含まれているかを表します。

たとえるなら、音を「ドレミの成分がそれぞれどれだけ入っているか」に分解する作業の、2次元版です。楽譜のどの音がどれだけ鳴っているかを見るのと同じ要領で、画像のどの細かさの模様がどれだけ入っているかを見ます。

実装は Cooley-Tukey の FFT を自前で書いています。素朴に定義どおり計算すると 640×480 で 10¹¹ 回の掛け算になり現実的でないところを、「偶数番目と奇数番目に分けて再利用する」ことで N log N まで落としています。2次元は「行ごとに1次元 → 列ごとに1次元」に分けられる(分離可能)ので、1次元の FFT がひとつあれば足ります。

F(u, v) = Σ_x Σ_y f(x, y) · exp( −2πi (ux/W + vy/H) )
f(x, y) = (1/WH) Σ_u Σ_v F(u, v) · exp( +2πi (ux/W + vy/H) )
表示しているのは log(1 + a·|F| / max|F|) / log(1 + a) (a = 10^対数の効き)
計算量:定義どおりなら O(N²)、FFT なら O(N log N)

注意点・見どころ

▲ 目次へ戻る

周波数フィルタ

パラメータ

名前種類既定値範囲・選択肢
種類selectlowpassローパス(細かい成分を落とす=ぼかす) / ハイパス(大きな明暗を落とす=輪郭だけ) / バンドパス(ある細かさだけ通す) / バンドストップ(ある細かさだけ落とす) / ノッチ(特定の1点を潰す=周期ノイズ除去)
切り方selectgauss理想(崖のように切る) / ガウシアン(なだらかに切る) / バターワース(切れ味を次数で選ぶ)
バターワースの次数range21 〜 10(刻み 1)
しきい周波数range0.060.005 〜 0.5(刻み 0.005)
帯の幅range0.050.005 〜 0.4(刻み 0.005)
ノッチの位置 u(横)range0.18-0.5 〜 0.5(刻み 0.002)
ノッチの位置 v(縦)range0.09-0.5 〜 0.5(刻み 0.002)
ノッチの半径range0.030.005 〜 0.2(刻み 0.005)
対象selectrgbRGB 個別(色のまま処理) / 輝度のみ(3倍速い)
境界処理(2の冪への埋め方)selectreflect鏡映で埋める(既定) / ゼロで埋める
ビューアに出すものselectimage処理後の画像 / フィルタを掛けたあとのスペクトル

原理

空間領域での畳み込みは、周波数領域では「掛け算1回」になります(畳み込み定理)。そこで画像を FFT でスペクトルに直し、残したい成分に 1、消したい成分に 0 に近い値を掛けてから逆変換します。中心付近を残せばローパス(ぼかし)、外側を残せばハイパス(輪郭抽出)、輪状に残せばバンドパスです。

たとえるなら、オーディオのイコライザです。低音つまみを下げるのがハイパス、高音つまみを下げるのがローパス。特定の周波数だけをピンポイントで削るのがノッチ(ハウリング対策と同じ考え方)で、画像では周期ノイズの除去に使います。

G(u, v) = F(u, v) · H(u, v)、  g = IFFT(G)
r = √(u² + v²)(正規化周波数、単位はサイクル/画素)

理想ローパス  : H = 1 (r ≤ D₀), 0 (r > D₀)
ガウシアン   : H = exp( −r² / 2D₀² )
バターワース  : H = 1 / (1 + (r/D₀)^(2n))
ハイパス    : H_hp = 1 − H_lp
バンドパス   : H = H_lp(D₀+w/2) · (1 − H_lp(D₀−w/2))
ノッチ     : H = 1 − D(‖(u,v)−(u₀,v₀)‖) − D(‖(u,v)+(u₀,v₀)‖)

注意点・見どころ

▲ 目次へ戻る

スペクトルマスク(手で塗る)

パラメータ

名前種類既定値範囲・選択肢
スペクトル(ドラッグで遮る/右ドラッグで戻す)spectrum(初期状態)スペクトルの上をドラッグして編集
マスクの縁のぼかしrange20 〜 10(刻み 1)
反転(塗ったところだけ通す)checkboxfalseオン / オフ
対象selectrgbRGB 個別(色のまま処理) / 輝度のみ(3倍速い)
境界処理(2の冪への埋め方)selectreflect鏡映で埋める(既定) / ゼロで埋める
ビューアに出すものselectimage処理後の画像 / マスクを掛けたあとのスペクトル

原理

周波数フィルタの通過率を、式で決める代わりに手で描きます。右のスペクトルを筆でなぞると、その周波数成分が落ちます。落とした状態で逆変換すれば、その成分だけが抜けた画像が戻ってきます。

たとえるなら、録音した音を波形ではなくスペクトログラムの上で編集する作業です。「この帯域のこの音だけ消す」を、耳ではなく目で狙って行います。画像でも同じことができる、というのがこの処理の主張です。

筆は必ず点対称の位置にも同時に乗ります。実数の画像のスペクトルは F(−u, −v) = conj(F(u, v)) を満たしていて、片側だけ消すとこの対称が崩れ、逆変換の結果に虚部が残って絵が壊れるためです。

G(u, v) = F(u, v) · M(u, v)、  g = IFFT(G)
M は手描きのマスク(0 = 遮る 〜 1 = 通す)
マスクは正規化周波数 −0.5〜0.5 を 128 等分した格子で持ち、
対称条件 M(−u, −v) = M(u, v) を塗るときに強制している

注意点・見どころ

▲ 目次へ戻る

ノイズと評価

ノイズ付加

パラメータ

名前種類既定値範囲・選択肢
種類selectgaussガウシアン(読み出しノイズ) / ソルト&ペッパー(欠陥・伝送エラー) / ショット(光子数のゆらぎ) / 周期ノイズ(斜め縞。周波数領域で消せます)
標準偏差 σrange201 〜 60(刻み 1)
飛ぶ画素の割合range0.050.005 〜 0.3(刻み 0.005)
最大光子数range303 〜 300(刻み 1)
縞の間隔range53 〜 30(刻み 0.5)
縞の向きrange270 〜 175(刻み 1)
縞の濃さrange305 〜 60(刻み 1)
色ごとに独立に乗せる(色ノイズになります)checkboxfalseオン / オフ
乱数の種range11 〜 20(刻み 1)

原理

ノイズは「どこから来たか」で性質が変わり、性質が違えば効く除去手法も変わります。ここでは由来の異なる3種類を分けて乗せられるようにしています。

ガウシアンノイズは、センサの読み出し回路などで全画素に薄く乗る加算性のノイズです。値は元の明るさに関係なく、平均0・標準偏差σの正規分布で揺れます。

ソルト&ペッパーノイズは、一部の画素だけが真っ白か真っ黒に飛ぶノイズです。欠陥画素や伝送エラーが由来で、「少数の画素が完全に壊れる」という点で他の2つとまったく違います。

ショットノイズは、光そのものの粒々しさから来ます。同じ明るさの面を撮っても、届く光子の個数はポアソン分布でばらつきます。暗い部分ほど相対的なばらつきが大きくなるのが特徴で、この点だけが他の2つと違います。

周期ノイズは、上の3つとまったく毛色が違います。ランダムではなく、一定の間隔でくり返す縞が絵に重なったものです。印刷物をスキャンしたときの網点、電気的な干渉、機械の振動などが由来で、実際に起きるのはたいてい斜めの縞です。ランダムでない=規則があるということは、周波数領域で見れば一点に集まるということでもあります。だからこれだけは、絵をぼかさずに縞だけを抜き取れます。「スペクトルマスク」や「周波数フィルタ」の出番はここです。

たとえるなら、ガウシアンは「全員の回答に薄く測定誤差が乗る」状態、ソルト&ペッパーは「回答用紙が数枚だけ破れて読めない」状態、ショットは「そもそも集まった票数が少ないので割合がぶれる」状態、周期ノイズは「録音にハムが混じっている」状態です。ハムは決まった高さの音なので、その音だけを止められます。対処のしかたがそれぞれ違うことが想像できると思います。

ガウシアン:g = f + N(0, σ²)
ソルト&ペッパー:確率 p で g = 0 または 255、それ以外は g = f
ショット:g = Poisson(f · λ_max / 255) · 255 / λ_max
(ショットだけは f に依存する=信号依存ノイズ)
周期:g = f + A · sin(2π(u₀x + v₀y))、u₀ = cosθ / T、v₀ = sinθ / T
(T は縞の間隔、θ は向き。ランダムでないので乱数の種は効かない)

注意点・見どころ

▲ 目次へ戻る

ノイズ除去の比較

パラメータ

名前種類既定値範囲・選択肢
表示selecttile4分割で並べる(実演向け) / ノイズあり(全解像度) / メディアン(全解像度) / バイラテラル(全解像度) / ガウシアン(全解像度)
ノイズの種類selectgaussガウシアン(読み出しノイズ) / ソルト&ペッパー(欠陥・伝送エラー) / ショット(光子数のゆらぎ)
ノイズの σrange201 〜 60(刻み 1)
飛ぶ画素の割合range0.050.005 〜 0.3(刻み 0.005)
最大光子数range303 〜 300(刻み 1)
ノイズを色ごとに独立に乗せるcheckboxfalseオン / オフ
乱数の種range11 〜 20(刻み 1)
メディアンの窓の半径range11 〜 4(刻み 1)
バイラテラルの σ_spacerange20.5 〜 5(刻み 0.1)
バイラテラルの σ_colorrange402 〜 100(刻み 1)
ガウシアンの σrange1.50.3 〜 6(刻み 0.1)

原理

ノイズの種類によって、効く除去手法が変わります。それを同じ画像・同じノイズで並べて確かめるための処理です。原画にノイズを乗せ、メディアン・バイラテラル・ガウシアンの3手法で消し、原画との PSNR / SSIM を並べます。

見どころは2つあります。1つめは「万能な手法は無い」こと。ソルト&ペッパーにはメディアンが圧勝しますが、ガウシアンノイズでは最下位に落ちます。2つめは「物差しによって答えが変わる」こと。PSNR で選ぶ手法と SSIM で選ぶ手法は、しばしば別になります。

たとえるなら、汚れの落とし方の比較です。泥はねなら1粒ずつ取り除く(メディアン)のが早く、全体のくすみなら面でならす(ガウシアン)ほうが早い。柄を消さずにくすみだけ取るには手間のかかるやり方(バイラテラル)が要る、という関係です。

PSNR = 10 · log₁₀( 255² / MSE )  MSE = 平均二乗誤差(RGB 3チャンネル)
SSIM = 平均 [ (2μxμy + C₁)(2σxy + C₂) / ((μx² + μy²+ C₁)(σx² + σy² + C₂)) ]
  窓は 11×11・σ=1.5 のガウシアン、C₁ = (0.01·255)²、C₂ = (0.03·255)²

注意点・見どころ

▲ 目次へ戻る

エッジ検出

Sobel / Prewitt

パラメータ

名前種類既定値範囲・選択肢
演算子selectsobelSobel(1:2:1) / Prewitt(1:1:1) / Scharr(3:10:3)
表示selectmag勾配強度 |∇f| / X方向の微分(横のエッジ検出) / Y方向の微分(縦のエッジ検出) / 勾配方向(色相)+強度(明るさ)
表示ゲインrange10.2 〜 8(刻み 0.1)

原理

明るさの変化率(1階微分)を求めます。ノイズがあると素の差分は暴れるので、微分する方向と直交する方向に平滑化を掛け合わせた 3×3 の窓を使います。Sobel は平滑化の重みが 1:2:1、Prewitt は 1:1:1、Scharr は 3:10:3 で、この重み以外は同じ骨格です。

たとえるなら、坂の傾きを測るのに、1歩ぶんの高低差だけで判断せず、横に少し幅を取って均してから測るようなものです。足元の小石(ノイズ)に振り回されずに済みます。

Sobel_x = [−1 0 +1; −2 0 +2; −1 0 +1] = [1 2 1]ᵀ ⊗ [−1 0 +1]
|∇f| = √(gx² + gy²)、  方向 θ = atan2(gy, gx)
分離可能なので 3×3 でも積和は 9 回でなく 6 回で済む

注意点・見どころ

▲ 目次へ戻る

Laplacian / LoG

パラメータ

名前種類既定値範囲・選択肢
種類selectlogLaplacian(4近傍) / Laplacian(8近傍) / LoG(ガウシアンで平滑化してから)
σ(LoG の平滑化)range1.60.4 〜 8(刻み 0.1)
表示selectsigned符号付き(128 が 0) / 絶対値 / ゼロ交差(エッジ位置)
表示ゲインrange40.5 〜 20(刻み 0.5)
ゼロ交差の最小段差range40 〜 30(刻み 0.5)

原理

2階微分をとります。1階微分(Sobel)がエッジで山になるのに対し、2階微分はエッジの手前で正、向こう側で負になり、エッジのちょうど真上で 0 を横切ります。この「ゼロ交差」がエッジの位置を1画素の精度で示します。方向を持たない(回転対称に近い)のも特徴です。

たとえるなら、坂道を車で走ったときの「傾き」ではなく「体にかかる前後の揺れ」を見るようなものです。坂の始まりで押しつけられ、終わりで引かれ、坂の真ん中では揺れがゼロになります。

∇²f = ∂²f/∂x² + ∂²f/∂y²
4近傍:[0 1 0; 1 −4 1; 0 1 0]   8近傍:[1 1 1; 1 −8 1; 1 1 1]
LoG:∇²(Gσ * f) = (∇²Gσ) * f   … 平滑化と微分の順序は交換できる

注意点・見どころ

▲ 目次へ戻る

Canny(段階表示つき)

パラメータ

名前種類既定値範囲・選択肢
表示する段階selectfinal① 平滑化後 / ② 勾配強度 / ③ 勾配方向(4方向に量子化) / ④ 非極大抑制の後 / ⑤ 二重閾値(白=強 / 灰=弱) / ⑥ ヒステリシス後(最終結果)
σ(平滑化)range1.40.4 〜 6(刻み 0.1)
下側しきい値range200 〜 255(刻み 1)
上側しきい値range550 〜 255(刻み 1)

原理

1986年に John Canny が「良い検出・良い位置決め・1本の応答」という3つの条件から導いた手順です。①ガウシアンで平滑化 →②勾配を求める →③方向に沿って非極大を抑制し1画素幅にする →④2つのしきい値で強/弱に分ける →⑤強エッジと繋がっている弱エッジだけを残す、の5段構えになっています。

たとえるなら、山の稜線を地図に引く作業です。まず等高線を滑らかにし、傾きを測り、尾根の頂点だけを残し、はっきりした尾根を確実に採用したうえで、そこから続いている自信のない部分も辿って繋ぎます。

① S = Gσ * f
② gx, gy = Sobel(S)、|∇S| = √(gx²+gy²)、θ = atan2(gy, gx)
③ NMS:|∇S|(p) が θ 方向の両隣以上でなければ 0
④ 強 = |∇S| ≥ high、弱 = low ≤ |∇S| < high
⑤ 強に8連結で繋がる弱だけを残す

注意点・見どころ

▲ 目次へ戻る

二値化とモルフォロジー

二値化(固定/大津/適応的)

パラメータ

名前種類既定値範囲・選択肢
閾値の決め方selectotsu固定(手で決める) / 大津の判別分析法(自動) / 適応的(場所ごとに決める)
閾値range1280 〜 255(刻み 1)
窓の半径range163 〜 60(刻み 1)
差の下駄 Crange6-30 〜 30(刻み 1)
窓の測り方selectmean平均(積分画像・窓によらず一定時間) / ガウシアン加重平均
白黒を入れ替えるcheckboxfalseオン / オフ

原理

明るさがしきい値を超えたら白、超えなければ黒に振り分けて、画像を2値だけの絵にする処理です。ここから先の「形を数える」処理(面積、個数、輪郭、モルフォロジー)は、たいていこの二値画像を入口にします。

難しいのは「しきい値をいくつにするか」だけで、この処理はその決め方を3通り用意してあります。固定は手で決める。大津はヒストグラムの形から自動で決める。適応的は1枚に1つではなく、画素ごとにその周りを見て決める。

たとえるなら、答案の合格ラインの引き方です。固定は「60点以上」と先に決め打つやり方、大津は点数の分布を見て「ここで2つの山が一番きれいに割れる」ところに引くやり方、適応的は「クラスごとの平均点を基準に引く」やり方です。教室によって難易度が違うなら、最後のやり方でないと公平になりません。

固定・大津:g(x, y) = 255 if f(x, y) > t, else 0

大津:t = argmax σ²_b(t)、σ²_b(t) = ω₀(t)·ω₁(t)·( μ₀(t) − μ₁(t) )²
  ω は各クラスの画素の割合、μ は各クラスの平均。分離度 η = σ²_b / σ²_total

適応的:g(x, y) = 255 if f(x, y) > mean_W(x, y) − C
  mean_W は (x, y) を中心とする窓 W の平均。積分画像 S を使うと
  窓の合計 = S(x₁,y₁) − S(x₀,y₁) − S(x₁,y₀) + S(x₀,y₀) の引き算3回で出る

注意点・見どころ

▲ 目次へ戻る

モルフォロジー(膨張・収縮・開閉)

パラメータ

名前種類既定値範囲・選択肢
操作selectdilate膨張(白をふくらませる) / 収縮(白をやせさせる) / オープニング(収縮→膨張) / クロージング(膨張→収縮) / トップハット(元 − オープニング)
構造要素の形selectrect四角(分離できる) / 十字(分離できる) / 円(分離できない)
構造要素の半径range21 〜 8(刻み 1)
反復回数range11 〜 3(刻み 1)
先に二値化する(大津)checkboxtrueオン / オフ
白黒を入れ替えるcheckboxfalseオン / オフ
結果を伸ばして表示するcheckboxtrueオン / オフ

原理

「構造要素」と呼ぶ小さな窓を画像の上で滑らせ、窓の中の最大値(膨張)か最小値(収縮)を採る処理です。二値画像なら「窓の中に白が1画素でもあれば白にする」のが膨張、「窓が全部白のときだけ白を残す」のが収縮になります。形そのものを太らせたり痩せさせたりする操作なので、面積や個数を数える前の下ごしらえによく使われます。

この2つを組み合わせると、大きさで選り分けができるようになります。収縮してから膨張する(オープニング)と、構造要素より細いものは収縮の段で消えてしまい、膨張しても戻ってきません。太いものだけが元の大きさに戻ります。逆順(クロージング)なら、小さな穴やすき間だけが埋まります。

たとえるなら、ふるいです。オープニングは目より小さい粒を落とすふるい、クロージングは隙間に砂を流し込んで埋める作業。トップハットは「ふるいで落ちたものだけを集める」操作にあたります。

膨張:(f ⊕ B)(x) = max{ f(x − b) : b ∈ B }
収縮:(f ⊖ B)(x) = min{ f(x + b) : b ∈ B }
オープニング:f ∘ B = (f ⊖ B) ⊕ B  クロージング:f • B = (f ⊕ B) ⊖ B
トップハット:f − (f ∘ B)
双対性:f ⊕ B = 255 − ( (255 − f) ⊖ B )

注意点・見どころ

▲ 目次へ戻る

センサと幾何

デモザイク(バイリニア vs AHD)

パラメータ

名前種類既定値範囲・選択肢
表示selecttile4分割で並べる(実演向け) / 原画(全解像度) / Bayer 生データ(全解像度) / バイリニア(全解像度) / AHD(全解像度)
CFA の並びselectRGGBRGGB(左上が R) / BGGR(左上が B) / GRBG(左上が G・右が R) / GBRG(左上が G・右が B)
Bayer の見せ方selectcolorモザイク(受け取った色に置く) / 素の値(グレー)
AHD の後処理(色差メディアン)range10 〜 3(刻み 1)

原理

デジタルカメラのセンサは、1つの画素で1つの色しか測れません。そこで画素ごとに赤・緑・青のどれか1色だけを通すフィルタを市松に並べ(カラーフィルタ配列、Bayer 配列)、足りない2色をあとから計算で埋めます。この埋める処理がデモザイクです。

つまり、私たちが見ているカラー写真は、画素の 2/3 が推測で埋められた絵だということになります。緑が半分、赤と青が 1/4 ずつなのは、人の目が緑の周波数帯に一番敏感で、明るさの手がかりの大半を緑が担っているからです。

ここでは原画をいったん Bayer 配列に間引いてから2つのやり方で戻し、原画と突き合わせます。ふだんは測れない「正解」が手元にあるので、どれだけ正しく埋められたかを数字で言えます。

たとえるなら、虫食いだらけの楽譜を復元する作業です。バイリニアは前後の音符の平均でとりあえず埋める。AHD は「横に読んだ場合」と「縦に読んだ場合」の両方を書いてみて、前後と自然につながるほうを採ります。

バイリニア(G の場合):Ĝ(x,y) = ( G(x−1,y) + G(x+1,y) + G(x,y−1) + G(x,y+1) ) / 4

AHD の方向別 G(Hamilton-Adams、横向き):
 Ĝ_h(x,y) = ( G(x−1,y) + G(x+1,y) ) / 2 + ( 2C(x,y) − C(x−2,y) − C(x+2,y) ) / 4
  C は中心画素の色(R か B)。第2項は「G と C の差が滑らかである」ことを使った補正

色差の補間:R̂ = Ĝ + bilinear( R − Ĝ )  B̂ = Ĝ + bilinear( B − Ĝ )

一様性:H_d(x) = #{ y ∈ N₄(x) : |L_d(x) − L_d(y)| ≤ εL かつ ‖ab_d(x) − ab_d(y)‖² ≤ εab }
  εL = min( 横向きの左右差の大, 縦向きの上下差の大 ) (εab も同様)
  3×3 の和が大きいほうの向きを採る

注意点・見どころ

▲ 目次へ戻る

アフィン変換(回転・拡大・せん断)

パラメータ

名前種類既定値範囲・選択肢
回転角range20-180 〜 180(刻み 1)
拡大率range10.2 〜 3(刻み 0.05)
せん断(横方向)range0-1 〜 1(刻み 0.05)
平行移動 xrange0-50 〜 50(刻み 1)
平行移動 yrange0-50 〜 50(刻み 1)
補間selectbilinear最近傍(1点) / バイリニア(4点) / バイキュービック(16点)
外側の扱いselectzero黒で埋める / 端の画素を伸ばす / 鏡映
往復させて誤差を見る(元に戻す)checkboxfalseオン / オフ

原理

画像を平行移動・回転・拡大縮小・せん断する処理です。この4つはまとめて2×3 の行列ひとつで書けて、どれだけ重ねがけしても行列の掛け算1回にまとまります。直線が直線のまま、平行な線が平行のまま保たれるのがアフィン変換の性質です。

実装で肝心なのは「向き」です。入力の画素を行き先へ飛ばす(順写像)と、行き先が飛び飛びになって隙間が空いたり、2つが同じ場所へ落ちたりします。そこで逆向きに、出力の画素ごとに「これはもとの画像のどこを読めばよいか」を逆行列で求めます(逆写像)。こうすると出力の全画素がちょうど1回ずつ埋まります。

ただし読む場所は小数になります。1.7 行目の 3.2 列目に画素はありません。そこで周りの画素から作るのが補間です。

たとえるなら、方眼紙に描いた絵を斜めの方眼紙に写す作業です。写す先のマスを1つずつ見て「元の絵ではこのあたり」と当たりを付けて色を決める。当たりの付け方が補間の種類にあたります。

順方向:[x'] = [a b][x − cx] + [cx + tx]
    [y']   [c d][y − cy]   [cy + ty]

 [a b] = zoom · [cosθ −sinθ] · [1 sh]
 [c d]          [sinθ  cosθ]   [0  1]

逆写像(実際に回す向き):もとの位置 = M⁻¹ · (出力の位置 − 中心 − 平行移動) + 中心

補間の重み
 最近傍    : 一番近い1点
 バイリニア  : (1−fx)(1−fy), fx(1−fy), (1−fx)fy, fx·fy の4点
 バイキュービック:Catmull-Rom(a = −0.5)の4×4 = 16点

注意点・見どころ

▲ 目次へ戻る

レンズ歪みと補正(樽型・糸巻き型)

パラメータ

名前種類既定値範囲・選択肢
することselectapply歪ませる(レンズを通した絵を作る) / 補正する(歪んだ絵をまっすぐに) / 歪ませてから補正する(誤差を見る)
歪み係数 k₁range-0.25-0.5 〜 0.5(刻み 0.01)
歪み係数 k₂range0-0.2 〜 0.2(刻み 0.01)
ズームrange10.5 〜 1.5(刻み 0.01)
格子を重ねてから歪ませるcheckboxtrueオン / オフ
補間selectbilinear最近傍(1点) / バイリニア(4点) / バイキュービック(16点)
外側の扱いselectzero黒で埋める / 端の画素を伸ばす / 鏡映

原理

レンズは光を曲げる道具なので、まっすぐな線がまっすぐに写るとは限りません。広角レンズでは画面の縁が中心に寄って、四角い建物の輪郭が樽のようにふくらんで見えます(樽型歪み)。望遠側では逆に外へ引っ張られ、糸巻きのようにへこみます(糸巻き型歪み)。

どちらも「中心からの距離だけが伸び縮みして、向きは変わらない」という形をしています。そこで中心からの距離 r を r·(1 + k₁r² + k₂r⁴) に置き換えるだけで、かなりよく表せます。奇数乗の項が無いのは、レンズが回転対称だからです。

補正はこの逆をやります。ただし「まっすぐな絵から歪んだ絵を作る」のと「歪んだ絵をまっすぐにする」のとでは、式を解く向きが逆になります。前者は式を逆に解く必要があり、解析的には解けないので数値で解きます。

たとえるなら、伸び縮みするゴムシートに絵を描く作業です。中心を押さえたまま外周を引っ張れば糸巻き型、外周を縮めれば樽型。補正は同じゴムを反対向きに引き戻すことにあたります。

歪みの式(中心からの距離だけを動かす)
 rᵈ = rᵤ · (1 + k₁·rᵤ² + k₂·rᵤ⁴)
  rᵤ … まっすぐな絵での半径 rᵈ … 歪んだ絵での半径(どちらも隅を 1 に正規化)
 k₁ < 0 で樽型、k₁ > 0 で糸巻き型

補正(出力=まっすぐ):出力の rᵤ から上の式で rᵈ を出し、そこを読む ← 式で直に出る
歪ませる(出力=歪んだ絵):出力の rᵈ から rᵤ を求める ← 上の式を Newton 法で解く

Newton 法:rᵤ ← rᵤ − f(rᵤ) / f'(rᵤ)  f(rᵤ) = rᵤ(1 + k₁rᵤ² + k₂rᵤ⁴) − rᵈ
       f'(rᵤ) = 1 + 3k₁rᵤ² + 5k₂rᵤ⁴

注意点・見どころ

▲ 目次へ戻る