2012年7月2日月曜日

ミニチュア写真ふうScript-Fu


ホントは高いところから逆あおりで撮影してみたいところなんだけど...
てもとにある写真をそれらしく。
光軸を傾けて撮影(ティルト、スイング)した画像っぽく見えるように処理してみます。
#光軸を並行にずらす操作(シフト、フォール、ライズ)はムツカシイってば。

写真によっては、実際に光軸を傾けて撮影したものと比べると、とってもつじつまの合ってないことになってるんだろうけども、つじつまの合わないところに注目するよりも、これはミニチュアだ、と強く思うことがダイジ。脳には見たいものが見えるもので。

ところで、あおり撮影ができるレンズはこんな動きをします。楽しい。

傾ける光軸を任意の位置、角度でお手軽に決められるのは、デジタル処理でやってしまうことのメリットではあります。これを実際の撮影で画角を変えずにやろうとすると、けっこう手間取るのではないかなぁ。

 
【レシピ】
  1. 画像をやや明るめに(gimp-curves-spline)
  2. 彩度を上げる(gimp-hue-saturation)
  3. ライティングを工夫(plug-in-lighting)
  4. 任意の軸を中心にぼかす(plug-in-focusblur)

ぼかしの前処理を含めて定番の手順と思います。
処理の順番はこのとおりでなくてもいいのかもしれないけども、今回はトーンジャンプしそうな処理を前に持ってきてみました。 あとの処理で少しでもごまかしが効くことを期待して。

Script-Fuはちょと長くなったので下のほうにのせてます。(へんなところに改行が入ってしまったので、コピーペーストの際はご注意を...)
各パラメータは適当に変えてもらうとして。
gimp-displays-flushをしつこく呼び出ししてるのは、ジブンの環境ではなぜかこうしないとうまく動かなかったから。設定ダイアログを表示せずに、一気に実行すると動くんだけどなぁ。んー。たまたま動いているだけだったり。スクリプトになにか根本的な原因があるのかもしれませぬ。

さてさて、ミニチュアが展示されている様子を想像すると、、、
それは自然光以外で明るめにライティングされているだろうし、実物よりもややディフォルメされて彩度高めで着色されているだろう、っていうことなのかしら。3. はパラメータしだいで周辺の光量を落とすのと近い効果にもなります。

plug-in-focusblurには深度マップを読み込む機能があります。今回はこれを利用してgimp-edit-blendを使って作成したグラデーションを読み込んでいます。
被写界深度を極端に浅くした画像をシミュレートすればミニチュアっぽく見えるようで、そうなると、しっかり作り込んだ深度マップを読み込めばもっとうまくぼかしができるし、何もティルト撮影を真似て軸を設定する必要もないわけで。
でも、そんな手間をかけずに、それらしく見えればそれはそれで。ね。
こんな簡易的な手法でも、けっこう脳をだませてしまうところを楽しんでみました。

と言いながら、何度もこればっかり試してたら、あまりミニチュアっぽく見えなくなってきてしまった。あれ...











Thanks,

hiro

(define (script-fu-miniature-fu img layer tone sat lighting focus-x focus-y focus-angle depth-of-field transition filter-radius s-radius s-threshold)
;(tracing TRUE)
  (let* (
         (tone-curve-points 4)                    ;tunable..
         (tone-curve #(0 0 32 80 80 140 255 255)) ;tunable..

         (width (car (gimp-drawable-width layer)))
         (height (car (gimp-drawable-height layer)))

         (start-x (* width focus-x))
         (start-y (* height focus-y))

         (pi (acos -1))
         (focus-angle-rad (* pi (/ focus-angle 180)))

         (focus-layer (car (gimp-layer-new img width height 0 "focus-layer" 0 0)))

         (pixels-max 0)
         (pixels-min 0)
         (transition-pixels 0)
         (d-x 0)
         (d-y 0)
         (end-x-b 0)
         (end-y-b 0)
         (end-x-f 0)
         (end-y-f 0)
         )

    (if (< width height)
        (begin
          (set! pixels-max height)
          (set! pixels-min width))
        (begin
          (set! pixels-max width)
          (set! pixels-min height))
        )
    (set! transition-pixels (* pixels-max transition))

    (set! d-x (* transition-pixels (sin focus-angle-rad)))
    (set! d-y (* transition-pixels (cos focus-angle-rad)))
    (set! end-x-b (- start-x d-x))
    (set! end-y-b (- start-y d-y))
    (set! end-x-f (+ start-x d-x))
    (set! end-y-f (+ start-y d-y))

    ; start process
    (gimp-selection-all img)
    (gimp-displays-flush)

    ; tone curve
    (if (= tone TRUE)
        (begin
          (gimp-curves-spline layer 0 (* tone-curve-points 2) tone-curve)
          (gimp-displays-flush))
        )

    ; saturation
    (if (> sat 0)
        (begin
          (gimp-hue-saturation layer 0 0 0 sat)
          (gimp-displays-flush))
        )

    ; lighting
    (if (= lighting TRUE)
        (begin
;          Intensity (Light tab in lighting UI): no parameter from script-fu (set to 1.0 as default)
;          ambient-intensity: 'Glowing'
;          diffuse-intensity: 'Bright'
;          diffuse-reflectivity: no control from lighting UI (set to 0.4 as default)
;          specular-reflectivity: 'Shiny'
;          highlight: 'Polished'
;          (plug-in-lighting 1 img layer layer layer FALSE FALSE 0 0 '(255 255 255) focus-x focus-y 0.7 -1 -1 1 Glowing Bright 0.4 Shiny Polished FALSE FALSE FALSE)
          (plug-in-lighting 1 img layer layer layer FALSE FALSE 0 0 '(255 255 255) focus-x focus-y 0.7 -1 -1 1 0 0.6 0.4 0 0 FALSE FALSE FALSE)
          (gimp-displays-flush))
        )

    ; blur
    (gimp-image-insert-layer img focus-layer 0 -1)
    (gimp-displays-flush)
    (gimp-edit-blend focus-layer 0 0 0 100 0 0 FALSE FALSE 1 0 FALSE end-x-f end-y-f end-x-b end-y-b)
    (gimp-displays-flush)
    (define df-curve (make-vector 256 0))
    (define df (* depth-of-field 128))
    (define a (/ 128 (- 128 df)))
    (define b (- 255 (* a 255)))
    (let* ((n 0))
      (while (< n (- 128 df))
             (vector-set! df-curve n (* n a))
             (set! n (+ n 1)))
      (while (< n (+ 128 df))
             (vector-set! df-curve n 128)
             (set! n (+ n 1)))
      (while (< n 256)
             (vector-set! df-curve n (+ (* n a) b))
             (set! n (+ n 1)))
      )
    (gimp-curves-explicit focus-layer 0 256 df-curve)
    (gimp-displays-flush)
    (plug-in-focusblur 1 img layer 1 filter-radius 50 focus-layer s-radius s-threshold) ;Bokeh(behind) 0:Flat, 1:Spherical, 2:Gaussian, 3:Ring, 4:Concave, 5:Brush
    (gimp-displays-flush)
    (gimp-image-remove-layer img focus-layer)
    (gimp-displays-flush)
    )

  (gimp-displays-flush)
;(tracing FALSE)
)

(script-fu-register
 "script-fu-miniature-fu"
 "Miniature Fu..."
 "tonecurve + saturation + lighting + blur"
 "hiro"
 "Copyright (C) 2012 hiro"
 "06/24/2012"
 "RGB*"
 SF-IMAGE "image" 0
 SF-DRAWABLE "drawable" 0
 SF-TOGGLE "tone" TRUE
 SF-ADJUSTMENT "saturation" '(80 0 100 1 10 0 0)
 SF-TOGGLE "lighting" TRUE
 SF-ADJUSTMENT "focus x" '(0.5 0 1 0.01 0.1 2 0)
 SF-ADJUSTMENT "focus y" '(0.5 0 1 0.01 0.1 2 0)
 SF-ADJUSTMENT "focus angle" '(0 -180 180 1 15 1 0)
 SF-ADJUSTMENT "depth of field" '(0.05 0 1 0.01 0.1 2 0)
 SF-ADJUSTMENT "transition" '(0.2 0 1 0.01 0.1 2 0)
 SF-ADJUSTMENT "filter radius" '(11 1 50 1 1 0 0)
 SF-ADJUSTMENT "shining radius" '(3 -1 50 1 1 0 0)
 SF-ADJUSTMENT "shining threshold" '(90 0 100 1 10 0 0)
 )

(script-fu-menu-register "script-fu-miniature-fu"
                         "<Image>/Filters/MyFu")
※GIMP 2.8.0で動作を確認しました。
※期待したとおり動かないかもしれません。
※動かなくても、何が起きても、たとえ悪魔が呼び出されたとしても、責任は取れません...