KansuImager
フィルタ作成マニュアル


第2版
2017/8/13
(C)2017, Noboru Imai

内容

概要

画像変換の基本は画素(Pixel)ごとの色を決定する変換関数を定義することで実現します. その際 RGB,XY または Shader モードを選択します. RGB モードでは Red, Green, Blue の各色成分ごとの色を決定する関数を定義します. XY モードでは X, Y座標成分ごとに元画像の位置を決定する関数を定義します. RGB モードは主に色彩フィルター,XY モードは変形フィルターの設計に用います. Shader モードではシェーダ言語(OpenGL GLSL の一種)で画像変換関数を記述し GPU の機能を直接使用して画像変換を行います. Shader モードの記述方法についてはShaderモードマニュアルをご覧ください.

変換関数中では,現在の画素位置や画像サイズなどを取得するための変数や定数. sin, cos などの算術関数,ガウスフィルタなどのフィルタ関数などが使用できます.

ユーザ自身がパラメータとその値を決定する計算式を定義し, 変換関数中で参照することができます.

オリジナルの線形フィルタを設計,使用するための関数も用意されています.

特殊な関数として, 条件によって計算実行を変更する IF 関数, 変換処理を強制中断する break 関数, 線分を描画する line, circle 関数, 顔認識を行う関数なども使用できます.

ユーザ定義の関数を解析しながら変換するので処理時間が一般的な画像処理アプリより掛かります. フィルタ設計時にはサイズの小さな画像でテストすることをお勧めします. なお,バーボタンの Convert から Resize を選択するとサイズ変更できます.

使用方法

Parameter & Equation

画像変換前,変換中,変換後のタイミングで計算を行い結果をパラメータに代入することができます. パラメータは他のパラメータの計算式や画像変換関数の中で使用できます.

パラメータを空欄にすると計算は実行されますが,結果は無視されます (描画関数などの実行時に用います).

計算タイミングの選択枝は以下の通りです.

計算は各計算タイミングごとに,定義順で実行されます. この順で前に定義したパラメータを参照することができます.

PrePixel が指定されたパラメータは色変換および座標変換関数の定義内で参照可能です.

Shader モードでは Pre パラメータのみ使用可能です. 詳しくはShaderモードマニュアルをご覧ください.

Post で定義したパラメータの値は,実行後に表示されます. また,これらはペーストボードにコピーされるので, メモアプリなどへコピーすることができます.

式の定義方法は を参照してください.

Mode

画像変換には RGBXY または Shader のいずれかのモードを選択します.

Function at Pixel (x,y)

ピクセルごとに実行される画像変換関数を定義します. Mode 選択によって編集項目が変更されます. RGB の場合には, RedGreenBlue が, XY の場合には,XYShader の場合には,Shader の編集欄が表示されます.

なお,処理対象のピクセルの座標は,変数 x,y に代入されています. 変数の詳細については 変数 を参照してください.

Red, Green, Blue

ピクセルごと,色成分ごとの色変換関数を定義します. 空欄の場合には元画像の色成分がそのままコピーされます.

色成分は [0,1] の範囲の実数です.

元画像の色成分は関数 R, G, B で取得できます.

X, Y

X座標,Y座標の成分ごとに座標変換関数を定義します.

変換前の位置の計算式を記述します. 変換前の位置の色が現在の位置(x,y)にコピーされます.

式の定義方法は を参照してください.

Shader

OpenGL のシェーダ言語 GLSL をベースとした iOS カスタムフィルター記述用の言語による記述を行います. 実行直前に GPU 用のマシン語にコンパイルされ GPU で並列処理されるので,高速な変換が期待できます.

ただし,RGB/XY モードとは全く異なる処理体系であるため,RGB/XY モードで使用可能なパラメータや式の定義,オペレータ,顔検出などの関数は使用できません.シェーダ言語の学習や,高解像度画像の高速変換が必要な場合に有用です.

Shader モードの記述方法についてはShaderモードマニュアルをご覧ください.

Range Out Mode

画像の外部を参照した場合の色の決定方法を指定します.

Background

Range Out Mode で Back Color を選択している場合に用いられる背景色を指定します.

座標系

原点は変換元画像の左上隅で,右方向はX軸プラス,下方向はY軸プラス方向です. (なお,Shade モードでは左下隅が原点で,上方向がY軸プラス方向です.)

変数

命名則

変数名で使用できる文字は英字とアンダースコアー'_' および数字です.

英字またはアンダースコアーから始まる必要があります.

大文字と小文字は区別されます.

関数と同名の変数も使用可能です.

定義済み変数・定数

文法

カッコ()つき四則演算式が定義でき,以下の演算子が使用できます.

ただし,* は省略できません. 式中にはこれ以前に定義されたパラメータや定義ずみ変数,定数,関数が使用可能です.

式中に '#' を挿入すると,これ以降はコメントとみなし,無視されます. ただし,break 関数では変換中断後にコメントが表示されます.

定義ずみ関数を以下に示します.

算術関数

算術関数は同名のC言語の関数を呼んでいます.

三角関数
( θ-角度[rad], a-底辺, b-高さ )
cos(θ)cos関数
sin(θ)sin関数
tan(θ)tan関数

三角関数の逆関数
( a-底辺, b-高さ, r-斜辺, 返値-角度[rad] )
acos(t)cosの逆関数, t=a/r
asin(t)sinの逆関数, t=b/r
atan(t)tanの逆関数, t=b/a, 出力範囲[-π/2,π/2]
atan2(b,a)tanの逆関数, 出力範囲[-π,π]

対数
ln(x)自然対数: ln x
log(a,b)対数: logab (=ln(b)/ln(a))
log10(x)常用対数: log10 x

その他
exp(x)指数関数: ex
pow(x,a)ベキ乗: xa
abs(x)絶対値: |x|
sqrt(x)平方根
floor(x)小数点以下の切り捨て
fmod(x,y)x÷y の余り

論理関数

ゼロを偽,ゼロでない数値を真とする論理関数が備わっています.

論理関数
IF(fg,x,y)判定関数
fgが真(fg≠0)の場合 x を評価(計算実行)し,偽(fg=0)の場合 y を評価してその値を返す.
NOT(fg)否定: fgが真の場合 0 を返し,偽の場合 1 を返す.
EQ(a,b)比較: a==b
LT(a,b)比較: a<b
LE(a,b)比較: a≤b
GT(a,b)比較: a>b
GE(a,b)比較: a≥b

Σ, Π 演算関数

総和演算 Σ を関数表現にした SIGMA と 総乗演算の Π を関数表現にした PI があります. これらは繰り返し処理にも用いることができます.

関数の第一引数では繰り返しに用いるパラータを定義します. パラメータ名はユーザ定義の変数とは異なる名称にして下さい. 第二引数はパラメータの初期値,第三パラメータは終了値を指定します. 第四引数は繰り返し適用される数式を指定します.

Σ, Π 演算関数
( i-パラメータ, i0-iの初期値, i1-終了値 )
SIGMA(i,i0,i1,eq)
PI(i,i0,i1,eq)

システム関数

実行状態を制御する関数として break が実装されています. IF 関数と組み合わせて条件によって処理を中断する場合などに使用します. 例えば,顔検出を伴う変換で,検出されなかった時に終了する場合などに使えます.

  IF(EQ(faceCount(),0), break(), 1) #No Face

システム関数
break()変換を強制中断する.
#コメントは中断後に表示される.

画素値取得関数

元画像の指定位置の画素値を取得する関数は以下の通り.

画素値関数
( (x,y):元画像上の座標, 返り値:[0,1]実数 )
M(x,y)濃淡色の取得
R(x,y)赤色成分の取得
G(x,y)緑色成分の取得
B(x,y)青色成分の取得
meanColor(cid,x,y,w,h)左上隅(x,y)から幅w,高さh領域の平均色成分の取得
cid:0-濃淡,1-赤,2-緑,3-青成分

組み込みフィルター

元画像にフィルタリングした画素値を取得する関数です.

組み込みフィルター
( cid:0-濃淡,1-赤,2-緑,3-青成分, (x,y):元画像上の座標, 返り値:[0,1]実数)
gaussF(s,cid,x,y)ガウスフィルタ(ぼかし処理)
s:ぼかし強度,(0,5]実数
averageF(s,cid,x,y)移動平均フィルタ(ぼかし処理)
s:平均の範囲,(0,8]整数
sobelF(cid,x,y)Sobelフィルタ(エッジ検出)

ユーザ定義フィルター

ユーザ自身で線形フィルターを設計し,適用することができます.

まず,線形フィルタのオペレータを定義する関数 opX(Xは2〜5の整数)を Pre タイミングで実行し,返り値でオペレータ番号を得ます. 次に,RGB モードの各色変換定義においてフィルタ実行関数 filter を実行します.

オペレータ定義
( eij:フィルタの成分, 返り値:オペレータ番号 )
op2(e00,op01,e10,e11)2x2 オペレータ
op3(e00,...,e22)3x3 オペレータ
op4(e00,...,e33)4x4 オペレータ
op5(e00,...,e44)5x5 オペレータ

元画像にユーザ定義フィルタリングした画素値を取得する関数は以下の通り.

フィルタ実行関数
filter(oid,cid,x,y)線形フィルタの実行
oid:オペレータ番号
cid:0-濃淡,1-赤,2-緑,3-青成分
(x,y):元画像上の座標, 返り値:[0,1]実数

描画条件

描画関数の作動条件を設定します. Pre または Post のタイミングで実行してください. その際,パラメータ欄を空欄にすることで不要な結果表示を防止できます.

描画設定関数
setLineColor(r,g,b,a)線色の設定.
色成分は[0,1]実数で指定.
r:赤成分
g:緑成分
b:青成分
a:不透明度(0:透明,1:不透明)
setFillColor(r,g,b,a)塗りつぶし色の設定.
setLineWidth(w)線幅設定
w:線幅[dot]
setAntiAliasing(fg)アンチエイリアシングのOn/Off
fg:1-On,0-Off

描画関数

線分などを描画します. Post のタイミングで実行してください. その際,パラメータ欄を空欄にすることで不要な結果表示を防止できます.

描画関数
line(x0,y0,x1,y1)(x0,y0)-(x1,y1)間を直線描画
circle(x,y,r)中心(x,y), 半径 r の円を描く
fillCircle(x,y,r)円を塗りつぶす
rectangle(x,y,w,h)左上(x,y), 幅 r, 高さ h の矩形を描く
fillRect(x,y,w,h)矩形を塗りつぶす

顔検出関数

元画像から顔の存在,位置などの情報を得ます. Pre または Post のタイミングで実行してください.

顔検出関数
( fid:顔番号[0,顔数-1]整数, item:0-口,1-右目,2-左目 )
faceCount()検出された顔数
faceX(fid)顔中心のX座標値
faceY(fid)顔中心のY座標値
faceWidth(fid)顔の幅
faceHeight(fid)顔の高さ
faceItemExist(fid,item)顔のパーツの検出
1-検出,0-未検出
faceItemPosX(fid,item)顔のパーツX位置
faceItemPosY(fid,item)顔のパーツY位置
bigFaceID()最も大きな顔の番号
-1:未検出

フィルタ作成例

ミラーリング

画像の左半分を中央で折り返し右半分に貼り付けた画像を作成するユーザ定義フィルタを作成手順を示します.

  1. 新規にフィルタを作成します.
  2. Mode を XY に設定します.
  3. X関数欄に以下を記述します.
    IF(LT(x,W/2),x,W-x)

XY モードでは元画像の指定位置の画素を現在の画素位置(x,y)にコピーします. X関数とY関数は各画素に対して繰り返し実行されます. 本ミラーリング処理はX座標のみの変換を行うのでY関数欄は空欄にします.

LT(a,b) 関数は a<b の場合 1 を,そうでなければ 0 を返します. 本例では W は画像幅なので,x<W/2 すなわち x が中央より左にある場合に 1,右にある場合に 0 となります.

IF(a,b,c) 関数は a≠0 の場合 b の計算を実行し,a=0 の場合 c の計算を実行してその値を返します. よって 本例では x が左側にある場合には x そのものが,右側にある場合には W-x の値を返します.

減色処理

パレメータの使用例として, モノクロの減色処理を実行するフィルタを作成します. 元画像の濃淡値を取得して5段階の明るさに直します.

  1. 新規にフィルタを作成します.
  2. Add Parameter をタップしてパラメータを追加します.
  3. パラメータ名を m, 計算タイミングを Pixel にし,計算式を以下のように記述します.
    M(x,y)
  4. Add Parameter をタップしてパラメータを追加します.
  5. パラメータ名を c, 計算タイミングを Pixel にし,計算式を以下のように記述します.
    0.2*(U(m)+U(m-0.2)+U(m-0.4)+U(m-0.6)+U(m-0.8))
    または
    0.2*SIGMA(i,0,4,U(m-0.2*i))
  6. Mode を RGB に設定します.
  7. Red, Green, Blue 関数欄全てに以下を記述します.
    c

M(x,y) 関数は指定位置の元画像の濃淡値を返します.変数 x, y には現在の位置が代入されています. 式の見易さと実行速度を考慮してこれを一旦パラメータ m に代入しておきます.

U(x) はステップ関数です.x<0 の場合には 0,x≥0 の場合 1 を返します. 例えば,本例のパラメータ c の式中にある U(m-0.2) は m が0.2未満ではゼロ,0.2以上であれば1となります. m の値は[0,1]の範囲の実数あり,m が増加すると c は 0.2,0.4,0.6,0.8,1.0 と階段状に変化します..

Red, Green, Blue 関数すべてに c を記述することでモノクロの画像が得られます.

アンシャープ処理

ユーザ定義の線形フィルタの事例として, ボケた画像を先鋭化するフィルタを作成します.

  1. 新規にフィルタを作成します.
  2. 先鋭化の強度を指定するパラメータ a を Pre タイミングで定義し,ゼロより大きな適当な値(例えば2)を設定します.
  3. オペレータ番号を代入するパラメータ oid を Pre タイミングで定義し,以下の式を記述します.
    op3(0,-a,0,-a,1+4*a,-a,0,-a,0)
  4. Mode を RGB に設定します.
  5. Red, Green, Blue 関数欄それぞれに以下を記述します.
    Red: filter(oid,1,x,y)
    Green: filter(oid,2,x,y)
    Blue: filter(oid,3,x,y)
  6. Range Out Mode を Mirror にします.

オペレータは行列の要素の値(式)を列優先に記述することで定義します. op3 は 3x3 行列で 9 つの値をとります.返り値はオペレータを識別する番号なのでパラメータ oid に保存しておきます.

filter(oid,cid,x,y) 関数はオペレータを元画像の指定位置に適用します. oid はオペレータ番号で,cid は適用する色成分を指定します.0は濃淡値で,1,2,3はそれぞれ赤,緑,青に対応します. (x,y) はオペレータを適用する中心の位置です.op3 の場合,(x,y)を中心に左右上下1ピクセルの幅の正方形領域に適用されます. 画像外部にはみ出す場合には,Range Out Mode で指定した条件が適用されます.

顔検出

顔検出を行い顔の位置に円を描きます.

  1. 新規にフィルタを作成します.
  2. Post 指定のパラメータ fn を定義します.
    faceCount()
  3. Post 指定で無名のパラメータを4つ定義し,以下の式を記述します.
    1. IF(EQ(fn,0),break(),5) #no face
    2. setLineColor(1,0,0,1)
    3. setLineWidth(2)
    4. SIGMA(fid,0,fn-1, circle(faceX(fid),faceY(fid), faceWidth(fid)/2))
  4. 変換関数は全て空欄にします.

無名パラメータ1では,顔数 fn がゼロであれば break 関数を実行し強制終了させます. その際,コメントの文字列 “no face” が表示されます.

無名パラメータ2,3は線の色と幅を指定しています.

無名パラメータ4では SIGMA 関数を用いて繰り返し処理を実現しています.

SIGMA 関数の最初の引数には繰り返し数を制御するパラメータを記述します. すでに定義されている場合には実行時に値が上書きされます. 定義されていない場合には新たなパラメータが定義されます. なお,実行後に別の計算式からも参照可能です. 本例では顔番号を入れる fid を記述しています.

SIGMA 関数の2つめと3つめの引数には制御パラメータの初期値と終了値を指定します. 制御パラメータは1回の処理を終了するごとに1が加算されます. 本例では,顔数は fn に格納されかつ顔番号はゼロから振られるので,初期値を 0,終了値を fn-1 としています.

SIGMA 関数の最後の引数には繰り返し実行する計算式を記述します. 本例では円を描く circle 関数を記述しています. circle 関数は便宜上1を返します.

circle 関数の引数では,顔の中心位置を取得する faceX および faceY 関数と顔幅を取得する faceWidth を呼んでいます. それぞれの引数に fid が用いられているので検出された全ての顔上に円が描かれます.

変換関数は全て空欄なので,変換モードに関わらず元画像がコピーされます. さらに Post 指定パラメータの処理として円が描画されます.


⬆︎
Ⓒ2017, Noboru Imai.