画像から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には、元画像と出力画像の対応関係が残ります。
なぜ正方形にするのか
必ず正方形でなければいけないわけではありません。ただ、複数素材を比較する時に、画像サイズや余白がそろっていると見やすくなります。ツールに投入する前の素材管理もしやすくなります。
特に小物やキャラクターの場合、上下左右に少し余白を入れておくと、輪郭が切れにくくなります。
Hi3Dに投入する前に見るところ
-
被写体が中央に配置されているか
-
足元や細いパーツが切れていないか
-
背景に余計な影や文字が残っていないか
-
同じ素材の処理前後をmanifestで追えるか
まとめ
3D生成の前処理は、派手な処理ではありません。しかし、素材が増えるほど効いてきます。入力画像をそろえ、出力との対応関係を残しておくと、生成結果の比較や再試行がかなり楽になります。
最終的な3Dモデルの品質だけでなく、その手前の素材管理もワークフローに入れておくと、Image-to-3Dを継続的に使いやすくなります。
