GIMPでPython-Fuを使った画像処理②

前回の続き。

GIMPでPython-Fuを使った画像処理① - かすブログ

今回は実際にクロスフィルタを実装する。 クロスフィルタはレンズフィルタを使った工学的なフィルタのため、 画像処理で実施するクロスフィルタは当然疑似的なものとなる。 GIMPのモーションぼかしフィルタを使って疑似的な光芒を作成した。

クロスフィルタを使った写真の例 光が十字状に輝いているのがクロスフィルタの効果。 頂点の数はカメラの光芒の数に依存する。この写真では4枚。

★参考にしたサイト★

・スプライン曲線のメソッド leware.net

★環境★

★内容★

[GIMP] クロスフィルタ合成用のレイヤを作成

まず最初に、クロスフィルタ合成用のレイヤを作成する。 ここでは黄色の1dotだけ以外を透明にしたレイヤを新規に追加した。 この1dotにフィルタをかける。

[python-fu] クロスフィルタを実装

疑似的だが以下のようにしてクロスフィルタの画像処理を作成した。

  1. 高輝度部分(今回は黄色の1dot)にモーションぼかしフィルタを光線にしたい方向に角度・長さを設定してフィルタをかける
  2. モーションぼかしフィルタ1回だと先細りしないので, 少しlengthを長くしてもう一度同じ方向にモーションぼかしフィルタをかける
  3. GIMPで実行してみるとかなり透明に近くなってしまうので、alphaのトーンカーブを調整して光線が見えるようにする。

フィルタ処理はトーンカーブの調整が少し難易度が高め。フィルタをかけるだけなら簡単に実装できる。 レイヤの扱いも簡単にできるようにapiが用意されていて使い勝手が良かった。 またundoグループという、undo一回で戻すグループを指定できるのも素晴らしい。

# -*- coding: utf-8 -*-

####################
# import
####################
# gimpfu用
from gimpfu import *

# ファイル入出力用
import sys

####################
# parameters
####################

# --verboseなら%USER_PROFILE%のパス、
# 通常起動なら.xcfファイルがあるパスに出力される
OUTTXT_PATH = "stdout.txt"
PW = 10
PH = 10

####################
# method
####################


# spline曲線を256点のポイントにして返すメソッド
def spline_to_points(spline):
    points = [ k/255.0 for k in range(256) ]
    x0 = 0.0
    y0 = 0.0
    ix = 0
    x0 = spline.pop(0) # remove initial (0.0,0.0)
    y0 = spline.pop(0)
    while spline:
        x = spline.pop(0)
        y = spline.pop(0)
        while ix < 256:
            xi = ix / 255.
            if xi > x:
                break
            points[ix] = ((x-xi) * y0 + (xi-x0) * y) / (x-x0)
            ix += 1

        x0 = x
        y0 = y
    return points


def cross_filter_core(image, layer):

    kobo = 4 # 光芒の数の半分、光芒は偶数のみ可能

    mblur_type = 0      # リニアモーション
    mblur_length1 = 5   # length(1回目)
    mblur_length2 = 10  # length(2回目)
    angle_offset  = 0   # angle offset
    mblur_cx = 5        # center x
    mblur_cy = 2        # center y
    gauss_h = 3         # gauss h
    gauss_v = 3         # gauss v

    # レイヤーグループを追加
    layer_group = pdb.gimp_layer_group_new(image)
    pdb.gimp_image_insert_layer(image, layer_group, None, 0)

    angle = angle_offset
    angle_dx = 360 / (kobo * 2)
    for n in range(kobo):

        # レイヤーをコピー
        work_layer = pdb.gimp_layer_copy(layer, 1)  # alphaチャンネルを追加
        pdb.gimp_image_insert_layer(image, work_layer, layer_group, 0) # レイヤーグループに追加

        # 角度を更新
        angle += angle_dx

        # ガウスフィルタIIR処理実行
        # pdb.plug_in_gauss(image, work_layer, gauss_h, gauss_v, 0) # 0: IIR

        # モーションぼかし処理実行
        pdb.plug_in_mblur(image, work_layer, mblur_type, mblur_length1, angle, mblur_cx, mblur_cy)
        pdb.plug_in_mblur(image, work_layer, mblur_type, mblur_length2, angle, mblur_cx, mblur_cy)

        # アルファチャンネル調整
        points = spline_to_points([0.0, 0.0, 0.2, 0.8])
        pdb.gimp_drawable_curves_explicit(work_layer, HISTOGRAM_ALPHA, 256, points)

    # レイヤーのマージ
    dst_layer = pdb.gimp_image_merge_layer_group(image, layer_group)
    dst_layer.name = "cross_filter"

def cross_filter(image, layer):

    try:
        # 処理開始
        gimp.progress_init("Discolouring " + layer.name + "...")

        # undoグループ開始
        pdb.gimp_image_undo_group_start(image)


        # クロスフィルタの実体
        cross_filter_core(image, layer)

    finally:
        # undoグループ終了
        pdb.gimp_image_undo_group_end(image)

        # 処理終了
        pdb.gimp_progress_end()


# 引数はregisterで登録するときに指定する。
def plugin_main(image):

    layer = pdb.gimp_image_get_active_layer(image)

    # cross_filter実行
    cross_filter(image, layer)



####################
# スクリプト登録
####################
# メニューバーの My にcross_filterを追加(画像を開くまで実行不可)

prms = [
    (PF_IMAGE, "image",       "Input image", None)
    # (PF_DRAWABLE, "drawable", "Input drawable", None)
    ]
register(
    "cross_filter",             # name
    "my cross filter",          # blurb (宣伝文句),
    "help: this is my filter",  # help
    "skattun",                  # author
    "(C) 2023 skattun",         # copyright
    "2023/5/5",                 # date
    "cross_filter",             # menupath(not use)
    "RGB*",                     # imagetypes
    prms,                       # params
    [],                         # results
    plugin_main,                # function
    menu = "<Image>/My")        # menu path設定

####################
# main
####################
m

[spline_to_points()] スプライン用のポイントデータ作成について

トーンカーブ調整用に渡す配列データを生成するため、折れ点位置を与えるとトーンカーブ用の配列を生成するメソッドを リンクからもらって実装した。与えた点を通る直線を計算して、直線補完する。

[GIMP] 実行結果

身代わり人形の目元を輝かせることができた。

元画像 / フィルタ用黄色点 / フィルタ適用後