Blender AI Wiki / Русский Поиск

SETUP 47: ZERO123 / INSTANTMESH

Zero123 / Zero123++ превращают одно фото в набор новых ракурсов. InstantMesh берёт эти ракурсы (или одно фото и делает ракурсы сам) и восстанавливает текстурированный меш за минуты на GPU. Настраиваем локальный запуск обеих частей и разбираем главную проблему: качество результата определяется не мод

⚙️ Сетапы ⭐⭐⭐ полная 11 блоков кода обновлено 2026-11-12

ID: SETUP-47 | Type: Multi-view 3D | Difficulty: ⭐⭐⭐ | Time: 1.5-2 h

Когда применять: когда есть одна фотография объекта и нужен текстурированный меш — а облачный API нельзя или не хочется. Цепочка: диффузионная модель дорисовывает ракурсы, InstantMesh собирает из них геометрию.

🎯 ЦЕЛЬ

Zero123 / Zero123++ превращают одно фото в набор новых ракурсов. InstantMesh берёт эти ракурсы (или одно фото и делает ракурсы сам) и восстанавливает текстурированный меш за минуты на GPU. Настраиваем локальный запуск обеих частей и разбираем главную проблему: качество результата определяется не моделью, а согласованностью промежуточных ракурсов. Если они «разъезжаются» — меш будет сломан, и никакая чистка в Blender это не спасёт.

[!NOTE] У Zero123 есть несколько репозиториев и весов (оригинальная работа «Zero-1-to-3» и улучшенные варианты). Имена скриптов, флаги и сами веса отличаются от репозитория к репозиторию. Прежде чем запускать, открой README того репозитория, который ставишь, и снимай имена оттуда.

📋 ЧТО ПОНАДОБИТСЯ

Компонент Ориентир Зачем
GPU 16 ГБ VRAM InstantMesh в дефолтных настройках; на 12 ГБ — со снижением разрешения
CUDA под твою карту иначе всё уходит в CPU и часы вместо минут
Диск 15-25 ГБ веса обеих моделей
Python 3.8-3.10 (репозитории старые) свежий Python часто ломает зависимости
Blender 4.x LTS импорт и чистка
trimesh для проверки геометрии диагностика до импорта

[!NOTE] Требования по VRAM зависят от настроек. Ориентир «16 ГБ» — то, на чём InstantMesh стабильно отрабатывает дефолтные параметры; на 12 ГБ приходится резать разрешение входа и число итераций. Точные значения смотри в README репозитория.

🛠️ НАСТРОЙКА

1. Готовим референс

from pathlib import Path
from PIL import Image

SRC = Path(r"C:/assets/refs/chair.jpg")
OUT_DIR = Path(r"C:/assets/ai3d/zero123"); OUT_DIR.mkdir(parents=True, exist_ok=True)

img = Image.open(SRC).convert("RGB")
# Модели ждут квадрат: центрируем кропом, а не ресайзом — иначе пропорции поплывут
side = min(img.size)
left, top = ((img.width - side) // 2, (img.height - side) // 2)
img = img.crop((left, top, left + side, top + side))
img = img.resize((512, 512), Image.LANCZOS)
img.save(OUT_DIR / "ref.png")
print("референс:", img.size, "исходник:", Image.open(SRC).size)

[!NOTE] 512×512 — типичный вход для Zero123-подобных моделей. Некоторые варианты принимают 256. Точный допустимый размер выводит модель при загрузке — посмотри лог, а не угадывай.

2. Ставим Zero123 / Zero123++

git clone <репозиторий zero123> && cd zero123
python -m venv .venv
# Windows:
.venv\Scripts\activate
# Linux/macOS:
# source .venv/bin/activate
pip install -r requirements.txt

# Дальше смотри README репозитория: имя скрипта генерации ракурсов и его флаги
ls *.py
# Проверяем GPU до того, как потратим час на установку
python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0) if torch.cuda.is_available() else '')"

3. Генерируем ракурсы

# Типовая форма вызова: скрипт с промптом, числом ракурсов и папкой вывода.
# Имя скрипта и точные флаги бери из README того репозитория, который клонировал.
python <скрипт_генерации_ракурсов>.py \
  --image ../ref.png \
  --num-views 6 \
  --output_dir ../views
# Проверяем результат ДО того, как отдавать его InstantMesh
from pathlib import Path
import os
from PIL import Image

VIEWS = Path(r"C:/assets/ai3d/zero123/views")
files = sorted(VIEWS.glob("*.png"))
print("ракурсов:", len(files))

# Кадры должны быть одинакового размера и без чёрных/пустых — иначе InstantMesh их выкинет
for f in files:
    im = Image.open(f)
    print(f.name, im.size, im.mode,
          "OK" if im.size[0] == im.size[1] and im.size[0] >= 256 else "ПРОБЛЕМА")

4. Ставим InstantMesh

git clone https://github.com/tencent/InstantMesh.git && cd InstantMesh
python -m venv .venv
# Windows:
.venv\Scripts\activate
# Linux/macOS:
# source .venv/bin/activate
pip install -r requirements.txt

5. Собираем меш

# Флаги читай в README: версии репозитория отличаются набором ключей
bash run.sh inputs/case_rendering  outputs/case   # вариант с готовым набором ракурсов
# или
python run.py inputs/case.png outputs/case        # вариант с одиночным изображением
# Второй вариант существует и часто даёт лучший результат, чем ручные ракурсы:
# модель сама дорисовывает вид. Сравни оба выхода.

6. Проверяем геометрию до импорта

import trimesh
from pathlib import Path

MESH = Path(r"C:/assets/ai3d/zero123/outputs/case/mesh.obj")
scene = trimesh.load(str(MESH), force="scene")
geoms = list(scene.geometry.values())
print("мешей:", len(geoms))
for name, g in scene.geometry.items():
    print(name, "verts:", len(g.vertices), "faces:", len(g.faces),
          "watertight:", g.is_watertight)

7. Импорт в Blender и чистка

import bpy
from pathlib import Path
from mathutils import Vector

def import_mesh(path: Path, coll="AI3D") -> bpy.types.Collection:
    c = bpy.data.collections.get(coll) or bpy.data.collections.new(coll)
    if c.name not in bpy.context.scene.collection.children:
        bpy.context.scene.collection.children.link(c)
    before = set(bpy.data.objects)
    bpy.ops.wm.obj_import(filepath=str(path))     # Blender 3.3+: C++-импортёр OBJ
    for o in set(bpy.data.objects) - before:
        for old in list(o.users_collection):
            old.objects.unlink(o)
        c.objects.link(o)
    return c

# coll = import_mesh(MESH)
# obj = next(iter(bpy.data.collections["AI3D"].objects))
# print(len(coll.objects), "объектов |", len(obj.data.polygons), "полигонов")

bpy.ops.object.select_all(action="DESELECT")
obj = bpy.context.view_layer.objects.active or next(iter(bpy.data.collections["AI3D"].objects))
obj.select_set(True)
bpy.context.view_layer.objects.active = obj

# Выборочное удаление мусорных граней, если меш «оброс» шумом
bpy.ops.object.mode_set(mode="EDIT")
bpy.ops.mesh.select_all(action="SELECT")
bpy.ops.mesh.select_non_manifold()
bpy.ops.mesh.delete(type="VERT")
bpy.ops.object.mode_set(mode="OBJECT")

# Масштаб и посадка на пол: без этого объект уезжает на 30 метров вверх
bpy.context.view_layer.update()
if obj.dimensions.z > 0:
    s = 0.5 / obj.dimensions.z
    obj.scale = (s, s, s)
bpy.context.view_layer.update()
obj.location.z -= min((obj.matrix_world @ Vector(c)).z for c in obj.bound_box)

smooth_ops = [o for o in dir(bpy.ops.object) if "smooth" in o]
print("итог:", tuple(round(v, 3) for v in obj.dimensions), "| smoothing ops:", smooth_ops)

[!NOTE] Удаление non-manifold-граней лечит типичную болезнь этой цепочки — «пузыри» и дырки от несогласованных ракурсов. Но если ракурсы разъехались принципиально, геометрия будет «смята» впустую: тогда правь вход, а не меш.

⚙️ КЛЮЧЕВЫЕ КОМАНДЫ И ПАРАМЕТРЫ

# Пакетно: 20 референсов через один запуск
python <скрипт_ракурсов>.py --image ref.png --num-views 6 --output_dir views/i%03d
Параметр Значение Когда менять
входной размер 512×512 256 для быстрой проверки идеи
--num-views 6 4 хватит для простых форм, 8+ для сложных
InstantMesh вход папка ракурсов ИЛИ одно фото сравни оба, результат разный
remesh_voxel_size не применяем меши уже достаточно чистые
dec.ratio 0.4–0.6 только если полигонов слишком много
seed фиксировать без seed повторный запуск даст другой меш

⚠️ ТИПОВЫЕ ОШИБКИ

Симптом Причина Решение
ImportError на torchao / разных версиях torch репозитории старые, конфликт версий отдельный venv на каждый репозиторий, не смешивать
Всё считается на CPU и очень долго нет CUDA-сборки torch поставь torch с CUDA под свою карту, проверь torch.cuda.is_available()
Меш «смят» в гармошку ракурсы геометрически несогласованы подай в InstantMesh одно фото, чтобы он дорисовал виды сам
InstantMesh падает на входе кадры разного размера или есть пустые проверь лог шага 3, перегенерируй
Текстура размытая на рёбрах мало ракурсов увеличь --num-views до 8
UV перекрываются реконструкция не гарантирует атлас bpy.ops.uv.smart_project()
wm.obj_import не найден версия старше 3.3 используй bpy.ops.import_scene.obj
Меш в километрах нет нормализации прогони шаг 8
Веса скачались не полностью оборвалась загрузка сверь размер с ожидаемым из README

🔗 СВЯЗИ

Связанные материалы

Подобраны по тегам и категории.