0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

画像素材を3D生成用にまとめて前処理するPythonスクリプト

0
Posted at

画像から3Dモデルを生成する作業では、入力画像の準備が意外と面倒です。背景を白にする、正方形にそろえる、ファイル名を整理する、処理前後を比較できるようにする。数枚なら手作業でもよいですが、素材が増えるとすぐに混乱します。

この記事では、複数の画像素材を3D生成用にまとめて前処理する簡単なPythonスクリプトを作ります。

やりたいこと

  • inputディレクトリ内の画像をまとめて読み込む

  • 透明背景があれば白背景に合成する

  • 正方形キャンバスに中央配置する

  • 長辺サイズをそろえる

  • 処理結果をmanifest.csvに出力する

処理した画像は、Hi3D のような画像入力型の 3Dモデル生成AI に渡す前の素材として使う想定です。

ディレクトリ構成

project/
  input/
    chair.png
    robot.png
    lamp.webp
  output/
  preprocess_images.py

必要なライブラリ

pip install pillow

スクリプト

from pathlib import Path
import csv
from PIL import Image

INPUT_DIR = Path("input")
OUTPUT_DIR = Path("output")
OUTPUT_DIR.mkdir(exist_ok=True)

TARGET_SIZE = 1024
PADDING_RATIO = 0.12
EXTENSIONS = {".png", ".jpg", ".jpeg", ".webp"}


def open_as_rgba(path: Path) -> Image.Image:
    return Image.open(path).convert("RGBA")


def composite_on_white(img: Image.Image) -> Image.Image:
    bg = Image.new("RGBA", img.size, (255, 255, 255, 255))
    bg.alpha_composite(img)
    return bg.convert("RGB")


def fit_to_square(img: Image.Image, target_size: int) -> Image.Image:
    # 元画像の縦横比を保ったまま、余白付きで正方形に配置する
    max_content = int(target_size * (1 - PADDING_RATIO * 2))
    w, h = img.size
    scale = min(max_content / w, max_content / h)
    new_size = (int(w * scale), int(h * scale))

    resized = img.resize(new_size, Image.Resampling.LANCZOS)
    canvas = Image.new("RGB", (target_size, target_size), (255, 255, 255))
    x = (target_size - new_size[0]) // 2
    y = (target_size - new_size[1]) // 2
    canvas.paste(resized, (x, y))
    return canvas


def process_one(path: Path) -> dict:
    original = open_as_rgba(path)
    white = composite_on_white(original)
    prepared = fit_to_square(white, TARGET_SIZE)

    out_name = f"{path.stem}_prepared.jpg"
    out_path = OUTPUT_DIR / out_name
    prepared.save(out_path, quality=95)

    return {
        "source": path.name,
        "output": out_name,
        "source_width": original.width,
        "source_height": original.height,
        "output_width": prepared.width,
        "output_height": prepared.height,
    }


def main():
    rows = []
    for path in sorted(INPUT_DIR.iterdir()):
        if path.suffix.lower() not in EXTENSIONS:
            continue
        rows.append(process_one(path))

    manifest_path = OUTPUT_DIR / "manifest.csv"
    with manifest_path.open("w", newline="", encoding="utf-8-sig") as f:
        writer = csv.DictWriter(
            f,
            fieldnames=[
                "source",
                "output",
                "source_width",
                "source_height",
                "output_width",
                "output_height",
            ],
        )
        writer.writeheader()
        writer.writerows(rows)

    print(f"processed: {len(rows)}")
    print(f"manifest: {manifest_path}")


if __name__ == "__main__":
    main()

出力例

processed: 3
manifest: output/manifest.csv

outputディレクトリには、白背景・正方形・1024pxにそろえた画像が保存されます。manifest.csvには、元画像と出力画像の対応関係が残ります。

Image

なぜ正方形にするのか

必ず正方形でなければいけないわけではありません。ただ、複数素材を比較する時に、画像サイズや余白がそろっていると見やすくなります。ツールに投入する前の素材管理もしやすくなります。

特に小物やキャラクターの場合、上下左右に少し余白を入れておくと、輪郭が切れにくくなります。

Hi3Dに投入する前に見るところ

15.png

  • 被写体が中央に配置されているか

  • 足元や細いパーツが切れていないか

  • 背景に余計な影や文字が残っていないか

  • 同じ素材の処理前後をmanifestで追えるか

まとめ

3D生成の前処理は、派手な処理ではありません。しかし、素材が増えるほど効いてきます。入力画像をそろえ、出力との対応関係を残しておくと、生成結果の比較や再試行がかなり楽になります。

最終的な3Dモデルの品質だけでなく、その手前の素材管理もワークフローに入れておくと、Image-to-3Dを継続的に使いやすくなります。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?