image-to-figure 是做什麼的?
目標
從一張角色圖片(插畫、概念圖或實體公仔照片)產出一個帶紋理的 3D 立體公仔,能從各個角度與角色相符:包含 Blender 主檔、乾淨的 GLB 格式、與四視圖比對的渲染圖,以及轉盤影片。擁有者負責核准花費與評斷外觀;您負責驅動各階段並在花費成本前發現問題。
不包含範圍:骨架綁定與動畫、擁有者無權使用的角色,以及在 Blender 中手動建模角色。
完成條件
views/view_front.png、view_left.png、view_back.png、view_right.png存在且尺寸一致,由img2fig crop以退出碼 0 產生。- 您已將四個視圖與參考圖片及彼此比較,並書面報告:每個配件在每個視圖中都位於身體的正確側邊,未出現參考圖中沒有的東西(最需檢查背面、口袋、腰帶與頭飾),且姿勢與地面線在各視圖間一致。任何差異已透過
img2fig edit修正並在模型階段前重新裁切。 models/<provider>/model.glb經由img2fig model --execute存在。img2fig prep退出碼為 0,其orientation不為ambiguous(或您已確認正面渲染朝向鏡頭),prep.dimensions_units[2]在 2.9 的 0.01 範圍內,且prep.faces_out低於或等於--faces(針對三角化輸入,如供應商 GLB)。- 您已檢視
renders/compare.jpg(上方為輸入視圖,下方為渲染圖)及renders/face.png,並報告每個視圖中相符與不符之處。 - 若擁有者需要影片,
turntable/turntable.mp4存在(img2fig turntable,退出碼 0)。 img2fig spend顯示總花費在擁有者核准的範圍內。
花費規則
- 呼叫付費 API 的命令(
lookdev、turnaround、edit、model)在未給予--execute時僅印出計劃與預估。向擁有者展示計劃的預估並獲得批准,可逐次批准或設定預算;然後將該預算傳入--budget(或設定IMG2FIG_BUDGET_USD;未設定時上限為 $5)。每次付費呼叫前會檢查工作目錄的帳本(spend.json,由img2fig spend彙總),若會超出則拒絕呼叫(退出碼 3)。失敗的呼叫仍以預估金額記錄,因為部分呼叫在供應商已計費後才失敗。 img2fig estimate --stages lookdev,turnaround,edit,model計算整次執行的價格。典型數量級:每次圖片呼叫低於 $0.30,每個 Tripo 模型約 $0.60,四供應商競價約 $4。預估值偏高;圖片呼叫的cost_from_usage_usd是基於 token 的實際數字。- 競價(
--provider all)約耗費七次 Tripo 執行。僅在擁有者要求或 Tripo 對此角色明顯失敗時才進行。
工作流程
img2fig doctor # 確認金鑰是否存在?Blender、ffmpeg 是否找到?
img2fig lookdev --ref character.png --description "..." # 計劃;獲得批准後添加 --execute
img2fig turnaround --ref character.png --description "..." # 使用最新的打光預覽圖片
img2fig crop # 產生 views/view_{front,left,back,right}.png
img2fig edit --fix "背面視圖:移除蝴蝶結下方的圓形尾巴;此處需為平裙。" # 僅在需要時使用
img2fig crop # 重新裁切:選取最新的組合圖或編輯結果
img2fig model # Tripo,計劃;獲得批准後使用 --execute
img2fig prep # 定向、標準化、減面、材質分級、渲染、compare.jpg
img2fig turntable # 產生 turntable/turntable.mp4
所有命令共享 --workdir DIR(預設為 $IMG2FIG_WORKDIR 或 ./figure_work);輸入預設為該目錄中前一階段的最新檔案。每個命令在標準輸出印出一個 JSON 物件;請讀取 ok、路徑、warning/warnings、next,以及失敗時的 error.type、error.message 和 error.detail(供應商 HTTP 狀態碼與主體、Blender 或 ffmpeg 退出碼與 stderr 末尾、日誌路徑)。
退出碼:0 成功(包含乾執行)、1 供應商錯誤、2 用法錯誤、3 超出預算、4 缺少金鑰/二進位檔/套件、5 Blender 或 ffmpeg 失敗、6 結果檢查失敗(組合圖未分割成預期視圖)、7 內部錯誤。
撰寫 --description
列出公仔必須保留的項目,並從角色視角與觀看者視角[括弧內]標明側邊:「她左側的綠色三葉草髮夾(正面觀看者的右側)」。描述參考圖片實際顯示的內容,而非您想生成的內容:圖片模型有時會將配件移到另一側,而參考圖片為準。
重要的 Prep 選項
--rot auto(預設)以平面著色在 0/90/180/270 度渲染模型,並與view_front.png逐一比較。若結果模糊,則回退至供應商的已知方向(僅 Tripo 已知;否則輸出會要求檢查正面渲染)。可傳入--rot DEG覆蓋。--grade matte(預設)、light(淺色服裝:白色保持乾淨)、dark(加深深色布料)、none。--keep-gloss 0.3保留來源中原本有光澤部分的粗糙度與金屬感。--blush=X,Z(可重複)以公仔分數為單位,在指定點塗上柔和腮紅;透過在renders/front.png中測量臉頰並執行img2fig point --x PX --y PY取得 X,Z。負值請用=寫入(--blush=-0.08,0.6),否則 argparse 會將其視為選項。--faces(預設 350000)設定面數上限;法線與顏色紋理保留精細細節。
已知陷阱(均經觀察)
- 圖片模型會發明細節,而 3D 模型會忠實建構它們。 一次轉盤圖曾在背部增加了角色從未有的絨球尾巴,以及在夾克口袋增加了徽章;3D 模型忠實複製了這兩者。請在圖片階段修正此問題(每次一個
--fix使用edit,然後再次crop和model)。不要修補網格。第一次編輯可能留下另一個發明(徽章變成了杯子蛋糕形裝飾),因此每次編輯後都要再次比對。 - 小特徵會模糊。 3840x2160 組合圖的每個視圖僅約 1000 像素寬,因此絨毛玩具的臉或手指在模型中會較模糊。沒有更大的組合圖可用;請判斷臉部渲染圖並告知擁有者,不要承諾清晰的微小細節。
- 供應商對方向的看法不一致。 Tripo 的 GLB 在匯入後面向 +X(需要旋轉 -90 度)。自動檢查會處理此問題;但仍需檢視正面渲染圖。
- 全霧面材質會扼殺水晶與光澤部分。 當角色有水晶、金屬或亮面部分時,請使用
--keep-gloss或--grade none。 - 手動建構的程序化角色無法達到公仔品質。 一個在 Blender 中用基本幾何體建模的角色無法正確呈現有機頭髮;圖片轉 3D 模型則可以。對於有機形狀,請勿回退至程序化建模。
- AgX 與 Standard 的比較。 渲染預設使用 AgX:高光不會裁切,但淺色與白色材質會偏灰且飽和度較低,這就是分級會提升飽和度的原因。
--view-transform standard更接近參考圖片的顏色,但會裁切亮部區域。方向檢查使用 Standard 渲染,以便顏色比較公平。 - Blender 中的 sRGB 與線性色彩。 在 Blender 中讀取 PNG 的像素顏色(
Image.pixels)會回傳編碼後的 sRGB 數值,而非線性數值。若您擴展 Blender 腳本,請在將其用作線性顏色前進行解碼。
資源與界限
- 金鑰僅來自環境變數:
OPENAI_API_KEY(圖片階段)與FAL_KEY(模型階段)。切勿印出或寫入檔案。 - Blender 作為外部二進位檔使用(在 5.2 上測試,預計 4.2 或更新版本可運作)(需在 PATH 上或設定
IMG2FIG_BLENDER);ffmpeg 用於轉盤影片。 - 工作目錄存放擁有者角色的生成圖片、模型與渲染圖。除非擁有者要求,否則請勿發布、上傳或提交;若擁有人物是從他人處授權取得,請視為私人資料。
- 提示模板位於
src/image_to_figure/prompts.py;--prompt-file可替換單次呼叫的模板。
3D 列印
img2fig print 將模型(預設 figure/figure_clean.glb;可使用 --model 指定任何 GLB、STL、OBJ 或 PLY;使用 --up auto 時,GLB/glTF/OBJ 視為 Y 軸向上,STL/PLY 視為 Z 軸向上)轉換為可直接列印的實體。需要 print 附加套件(uv pip install -e '.[print]');同時安裝 pymeshlab(GPL 授權,非依賴項)可在報告中增加明確的自相交面計數。
img2fig print --height 100 --base pedestal # 實心,FDM 或樹脂
img2fig print --height 130 --base pedestal # FDM 有薄壁部分:印大一點而非加厚
img2fig print --height 100 --base pedestal --hollow 2.0 # 樹脂:2 mm 壁厚,排水孔
img2fig print --model raw_tripo.glb --rot -90 --height 80 # 原始 Tripo GLB 面向 +X
完成條件:命令退出碼 0 且 checks.printable 為 true(防水、有效的 2-manifold(由 manifold3d 判定)、正體積);checks.parts 為 1,除非故意保留鬆散零件;checks.self_intersecting_faces 在可測量時為 0;output.height_mm 等於 --height 加上底座(在一個體素範圍內);您已檢視 print/figure_section.png(壁、空腔與排水孔)與 figure_preview_*.png 渲染圖,並報告 warnings 中的每個條目,特別是薄壁部分(checks.wall_thickness:thin_part_volume_fraction、largest_thin_parts 及其毫米位置;relief_volume_fraction 為良好表面細節,僅報告不增厚)及其處理方式。若使用了 --thicken,您需比較預覽渲染圖與未增厚版本,確認臉部、頭髮或配件上沒有新凸起;若無 Blender(無預覽圖),請檢查 thicken.added_mm3 數量級與 wall_thickness_before.thin_part_volume_mm3 相同(凸起會顯示為遠超此值的額外體積),並檢視剖面圖。
運作原理:表面被體素化(預設體素 = 高度 / 500),透過最小的形態學閉合(最多 8 個體素)密封間隙以包覆內部(voxelize 步驟會報告 gap_closing_voxels)並填充內部,因此開放邊緣、重疊殼層與自相交消失;然後符號距離場進行底座切割、底座、挖空與排水孔;行進立方體、Taubin 平滑化與 manifold3d 產生最終網格。小於約一個體素的細節會遺失,且距離小於閉合間隙的零件會融合。
選項:--min-wall(預設 1.0 毫米;樹脂可更低,FDM 通常需要 1.2 或以上)設定薄壁的標準;--thicken(預設關閉)將薄壁部分增長至該厚度,見下方說明;--fragments merge|remove|keep 搭配 --merge-gap(預設 2 毫米)決定浮動零件:在合併模式下,間隙內的零件以橋接方式連接,較遠的零件則保留並報告,絕不悄悄丟棄;小於 1 mm³ 的碎屑一律移除;--base flat|pedestal|none;--hollow WALL 搭配 --drain-hole 從下方為每個空腔鑽一個孔(小於 20 mm³ 的袋狀區域保持實心);--color 從模型紋理寫入頂點顏色的 PLY 檔案,用於全彩服務。STL 與 3MF 為單色。
薄壁部分。報告將薄壁部分(從較厚主體突出超過 --min-wall 的薄片、鰭片、股線、緞帶與繩索,且兩面距離接近)與表面浮雕(厚主體上的浮雕線條、股線邊緣、小點與凸起邊緣)區分開來。對於 FDM,建議印大一點:每個薄壁部分會隨公仔縮放(0.9 毫米緞帶在 100 毫米時為 1.17 毫米在 130 毫米時),不需重新塑形,且切片機的薄壁處理(Arachne 壁面、「偵測薄壁」)可列印大部分剩餘部分;體積的百分之零點幾在壁面內是正常且可接受的。當尺寸固定且少數薄壁部分必須實心列印時(緞帶環、呆毛、懸掛繩索、裙擺),使用 --thicken:它僅增長薄壁部分至約 --min-wall 並鈍化其尖端;浮雕永不增長。當 --thicken 後仍有薄壁部分時,警告會說明並建議印大一點或調整切片機設定,而非再次執行。定義邊緣:從主體突出超過 --min-wall 的浮雕(高窄脊線、深浮雕股線)視為薄壁部分並被鈍化;跨越兩個厚主體之間間隙的短薄網狀結構(約達兩倍 --min-wall)報告為浮雕,切片機可能丟棄它而留下孔洞,請在切片機預覽中檢查網狀結構。增長會向各個方向進行,因此 --thicken 也會稍微加長尖端,並可能融合距離小於 --min-wall 的薄壁部分。
建構過程觀察:二元距離場在未平滑化前會留下可見階梯(Taubin 平滑化,--smooth,預設 10 次迭代,保留體積);將頂點投影回來源表面會摺疊薄片,因此被放棄。平滑化與網格簡化都可能引入薄區域的自相交;命令會嘗試較少平滑化與較嚴格容差,直到檢查通過,並報告最終使用的設定(smooth_and_simplify 步驟)。挖空必須讓無法排水的袋狀區域保持實心,否則會形成密封空隙。在真實的圖片轉 3D 公仔案例中,兩個對稱的 120 mm³ 零件被建模為距離主體 1.3 毫米的獨立殼層;早期版本因它們恰好在 1 毫米合併間隙之外而將其移除,因此距離較遠的零件現在被保留並報告。在真實的 100 毫米公仔案例中,使用 --min-wall 1.2 時,早期的 --thicken 在臉部、頭髮、蝴蝶結與絨毛配件上覆蓋了小型圓形凸起:它將 1.2 毫米球體無法觸及的所有物體(包括淺浮雕如股線邊緣、浮雕睫毛與點)都視為薄壁,並將每個向各側增長 0.6 毫米(體積增加 5.5%)。在未增厚的同一個案例中,--min-wall 1.2 僅報告了 0.16% 的薄體積(大部分是裙邊飾帶與細繩),而 --thicken 覆蓋了整個公仔表面。因此建議:除非特定零件必須實心,否則先使用 --thicken false 印大一點;若必須使用 --thicken,請比較預覽渲染圖(有無 Blender 均可),確認臉部、頭髮、蝴蝶結和配件上沒有新凸起,且 thicken.added_mm3 約等於 wall_thickness_before.thin_part_volume_mm3。若凸起仍然存在,請增加 --min-wall(例如至 1.5 毫米)並減少平滑化迭代次數(例如 --smooth 5)。