blenderで、レンダリングとコンポジットとファイル整理の自動化のお話

全部乗せみたいなタイトル、質の悪いラノベみたいですね(笑)
さて、今回はどのようなことか、少し見ていきましょうかね


APIはちゃんと見てるかい?

これは自戒の念も込めておりますが、blenderの作業のほぼほぼ全てにはAPIというものがついて回っております

APIってなんだ

API(Application Programming Interface、アプリケーション・プログラミング・インターフェース)は、ソフトウェアやサービス間でデータや機能をやり取りするための仕組みやルールの集合です。APIは、異なるシステムやアプリケーションが互いに通信し、連携するための「橋渡し役」として機能します。

APIの役割

APIは以下のような役割を果たします:機能の提供: あるソフトウェアやサービスが持つ機能を、他のプログラムから利用できるようにします。
例:Google Maps APIを使うと、自分のアプリに地図機能を組み込むことができます。
データのやり取り: 異なるシステム間でデータを共有したり、受け渡ししたりするための手段を提供します。
例:天気予報APIを使うと、天気データを取得して表示できます。
開発の効率化: 既存の機能やデータを再利用できるため、開発者がゼロからすべてを作る必要がなくなります。

Deep Seekに聞いたよ

というようなものです
blenderでは特にどのコマンドにもコマンドにもAPIがあり、それを勉強するとPythonコードでblenderを動かすことができるようになっています
奥が深いのでまだまだ私はそういう域には達していません。。
とにかく勉強が必要ですね。。

blenderでAPIの見方

スクリプトのウィンドウ

blenderでは画面上部にある画面の構成の選択でスクリプトを選択すると左下にあるコマンドラインで実際に実行されているAPIを見ることができます。
ただ、これがコピペでそのまま使えるというものは少なくて結局は自分で使うためにある程度修正して使う必要があります

blender APIなどで検索をすると下記ページが出てきます

ここにblenderのAPIについて事細かく説明されております。
但し英語です。
これが日本人にとって結構な障害になりますね(笑)

Pythonも知らない、アドオンは諦めるべきか

そんなことは全然ない、そういう時代です。
今の時代にはAIがあります。とても優秀です。そりゃ人間が馬鹿にもなるわ、というくらいに優秀です

例えば

「blenderで基本的なアドオンのコードを教えて」
と聞くと

bl_info = {
    "name": "Simple Addon",
    "blender": (3, 0, 0),
    "category": "Object",
    "version": (1, 0),
    "author": "Your Name",
    "description": "A simple addon to demonstrate Blender's addon structure.",
}

import bpy

class SimpleOperator(bpy.types.Operator):
    bl_idname = "object.simple_operator"
    bl_label = "Simple Operator"

    def execute(self, context):
        print("Hello, Blender!")
        return {'FINISHED'}

class SimplePanel(bpy.types.Panel):
    bl_label = "Simple Panel"
    bl_idname = "VIEW3D_PT_simple_panel"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Simple Addon"

    def draw(self, context):
        layout = self.layout
        layout.operator("object.simple_operator", text="Say Hello")

def register():
    bpy.utils.register_class(SimpleOperator)
    bpy.utils.register_class(SimplePanel)

def unregister():
    bpy.utils.unregister_class(SimpleOperator)
    bpy.utils.unregister_class(SimplePanel)

if __name__ == "__main__":
    register()

ちゃんと動くかはともかく、確かめないと分かりませんが、一発でこんなに書いてくれます。
また、それに付随して解説も書いてくれます。

コードの説明bl_info: アドオンのメタデータを定義します。ここにはアドオンの名前、バージョン、作者、説明などを記述します。
SimpleOperator: bpy.types.Operatorを継承したクラスで、ボタンがクリックされたときに実行される操作を定義します。この例では、コンソールに「Hello, Blender!」と表示します。
SimplePanel: bpy.types.Panelを継承したクラスで、3Dビューポートに新しいパネルを追加します。パネル内にはボタンが表示されます。
register() と unregister(): アドオンをBlenderに登録・解除するための関数です。
アドオンのインストール方法Blenderを開き、Edit > Preferencesを選択します。
Add-onsタブを開き、Install...ボタンをクリックします。
上記のコードを.pyファイルとして保存し、そのファイルを選択してインストールします。
アドオンがリストに表示されるので、チェックボックスを有効にします。
アドオンの動作確認3Dビューポートの右側にあるサイドバーを開きます(Nキーを押すと表示されます)。
Simple AddonカテゴリにSimple Panelが表示されます。
Say Helloボタンをクリックすると、コンソールに「Hello, Blender!」と表示されます。
カスタマイズのヒント新しい機能を追加: SimpleOperatorクラスに新しいメソッドを追加して、独自の機能を実装できます。
UIの拡張: SimplePanelクラスのdrawメソッドを編集して、スライダーやテキストボックスなどのUI要素を追加できます。
他のBlender機能との連携: BlenderのAPIドキュメントを参照して、モデリングやアニメーションなどの機能と連携させることができます。
BlenderのAPIは非常に強力で、アドオンを作成することでBlenderの機能を大幅に拡張できます。ぜひ挑戦してみてください!

Deep Seekに聞いたよ

という感じです。すごいの是非使ってみてほしいです。
それで間違っていたら、間違っているようです。と共にエラーメッセージを送ったり、他にも要望を話して追加していくと、ある程度複雑なアドオンもしっかりと書いてくれます。
おそらく有料のものであれば更に最新の情報などに基づいて教えてくれるのだと思います。

コンポジットの気づき

今、デフォルトファイルでやっているコンポジットはこんな感じです

コンポジットの画面

このソーベルというフィルターが抽象性の高いものと相性良さそう、と思ってやり始めたのがきっかけです
でもそれをいちいち設定して保存して、というのが面倒になりました
コンポジットの中に、ファイル出力というものを見つけました
つまり、コンポジットの中で各設定、各段階のファイル出力が勝手に行われるというもの
おお、便利な物があるではないかと思ってはいたんですが、当然のごとく出力時のリネームの機能はありません
また壁を感じてしまった瞬間ですよね(笑)

アドオンにするしかないか。。。

ということでAIと相談して完成?させませした。

import bpy
import os
import shutil
import datetime

class SimplePanel(bpy.types.Panel):
    bl_label = "Render & Move Files"
    bl_idname = "VIEW3D_PT_render_move"
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'UI'
    bl_category = "Tool"

    def draw(self, context):
        layout = self.layout
        layout.operator("object.render_and_move")


class RenderAndMoveOperator(bpy.types.Operator):
    bl_idname = "object.render_and_move"
    bl_label = "Render and Move Files"

    def execute(self, context):
        # レンダリングを実行
        bpy.ops.render.render(write_still=True)

        # ファイルを移動
        source_folder = "D:/Blender/pic/auto/MAIN"
        destination_parent_folder = "D:/Blender/pic/auto"
        move_files_with_rename(source_folder, destination_parent_folder)

        self.report({'INFO'}, "Rendering and file move completed.")
        return {'FINISHED'}


def move_files_with_rename(source_folder, destination_parent_folder):
    # 今日の日付を取得 (YYYYMMDD形式)
    today = datetime.date.today().strftime("%Y%m%d")
    # 移動先のフォルダ名
    destination_folder = os.path.join(destination_parent_folder, f"{today}")

    # 移動先のフォルダが存在しない場合は作成
    if not os.path.exists(destination_folder):
        os.makedirs(destination_folder)

    # 移動元のフォルダ内の全ファイルを移動
    for file in os.listdir(source_folder):
        source_file = os.path.join(source_folder, file)
        destination_file = os.path.join(destination_folder, file)

        # 移動先で同じ名前のファイルが存在する場合
        if os.path.exists(destination_file):
            i = 1
            while True:
                new_name = f"{file[:-4]}-{str(i).zfill(3)}{file[-4:]}"  # 拡張子を含めたファイル名
                new_destination = os.path.join(destination_folder, new_name)
                if not os.path.exists(new_destination):
                    break
                i += 1
            destination_file = new_destination

        shutil.move(source_file, destination_file)

    print("ファイルの移動が完了しました。")


def register():
    bpy.utils.register_class(SimplePanel)
    bpy.utils.register_class(RenderAndMoveOperator)


def unregister():
    bpy.utils.unregister_class(RenderAndMoveOperator)
    bpy.utils.unregister_class(SimplePanel)


if __name__ == "__main__":
    register()

アドオンの動きについて

このアドオンでは

・実行でレンダリングを実施
・MAINというフォルダに一旦出力
・日付名(YYYYMMDD)フォルダがあれば、そのまま、なければ作成
・日付名フォルダに移動
・移動時に同名ファイルがあればリネーム、無ければそのまま保存

というような感じで動きます。
これだけでちまちまとファイル名を変える手間が無くなりました。
やはりプログラムというのは便利に使うべきものです

あとはある程度の応用で色々なものに波及させることができるので、楽しいです

ちなみにコード内のコメントについてはAIが勝手に入れてくれています。
それぞれの行の解説を求めても丁寧に行ってくれます。
大変ありがたい相棒のような場面が多く存在します。

少し違うファイルも含まれていますが、こんな感じフィルターの強弱別で画像の出力をしています

ファイラー

フィルターをかけるとフリンジが出るんです


未処理
処理後

これらを見比べると未処理でオブジェクトの輪郭で色のにじみが発生しているのがおわかりいただけると思います
写真的にはこのようなものはよくフリンジ、特に写真では紫色のフリンジが発生しますので、パープルフリンジや略してパーフリという名前で知られております

これの処理も最初はblenderの中でできないかなと少しだけ戦ってみたのですが、それでもいい手段が見当たらなかったので諦めて外部の写真編集ソフトにやらせることにしました。

写真編集、Raw現像ソフト「Art」というソフトについて少し

ダウンロードはここかな?

名前がシンプルなのでまぁ見つけにくい
毎回だれかのブログを経由している気がします
ご本家よりもブログが先に引っかかるのもまた実情…

ARTでのフリンジ処理

それぞれの色に対応させるようにバーを動かせるのでそれで適宜調整することで画像の中のフリンジを処理することが可能になります

ARTのAPIとかもあればこの辺も自動化できてしまいそうです(笑)
このARTにはいわゆるフィルムシュミレーションなどもついているので、ちゃんとした写真のRaw現像ソフトとして使うものです。
こういうフリンジ処理だけならGimpとかでもできそうですね(笑)

おわりに

こんな感じでとりとめもないような内容になりましたが、少しばかり気持ちの共有ができましたかね
blenderでもAPIの解説然り中身の開示自体はオープンですので誰でも見ることが出ます
そのため、AIに聞いたときとしても情報量が多いのだと思います
その辺もblenderの仕組みに感謝ですね

これからも何かしらの自分なりの発見をしたときにでも記事の更新をしていきますのでよろしくお願いします。

いいなと思ったら応援しよう!