Que fait image-to-figure ?
Objectif
À partir d'une image de personnage (une illustration, une fiche concept ou une photo d'une figurine), produire une figurine 3D texturée qui correspond au personnage sous tous les angles : un fichier maître Blender, un GLB propre, des rendus de révision par rapport aux vues de tourne-page, et une vidéo tournante. Le propriétaire approuve les dépenses et juge le rendu ; vous pilotez les étapes et détectez les problèmes avant qu'ils ne coûtent de l'argent.
Hors du champ : l'armature et l'animation, les personnages dont le propriétaire n'a pas les droits, et la modélisation manuelle du personnage dans Blender.
Terminé quand
views/view_front.png,view_left.png,view_back.png,view_right.pngexistent, toutes de la même taille, issues deimg2fig cropavec code de sortie 0.- Vous avez comparé les quatre vues avec l'image de référence et entre elles, et rapporté par écrit : chaque accessoire est du bon côté du corps dans chaque vue, rien n'apparaît qui ne soit pas dans la référence (examinez attentivement la vue arrière, les poches, les ceintures et les ornements de cheveux), et la pose et la ligne de sol correspondent entre les vues. Toute différence a été corrigée avec
img2fig editet la feuille a été recadrée avant l'étape du modèle. models/<fournisseur>/model.glbexiste suite àimg2fig model --execute.img2fig prepa renvoyé 0, sonorientationn'est pasambiguous(ou vous avez confirmé que le rendu de face fait face à la caméra),prep.dimensions_units[2]est à moins de 0,01 de 2,9, etprep.faces_outest inférieur ou égal à--faces(pour une entrée triangulée comme les GLB des fournisseurs).- Vous avez examiné
renders/compare.jpg(vues originales en haut, rendus en dessous) etrenders/face.png, et rapporté par vue ce qui correspond et ce qui ne correspond pas. turntable/turntable.mp4existe (img2fig turntable, exit 0) si le propriétaire souhaitait une vidéo.img2fig spendmontre un total dans les limites approuvées par le propriétaire.
Règles de dépenses
- Les commandes qui appellent une API payante (
lookdev,turnaround,edit,model) n'affichent qu'un plan et une estimation sauf si--executeest donné. Montrez l'estimation du plan au propriétaire et obtenez un feu vert, soit par appel, soit sous forme de budget qu'il fixe ; puis transmettez ce budget via--budget(ou définissezIMG2FIG_BUDGET_USD; sans cela, le plafond est de 5 $). Le budget est vérifié par rapport au journal du répertoire de travail (spend.json, résumé parimg2fig spend) avant chaque appel payant, et l'appel est refusé (code de sortie 3) s'il le dépasse. Les appels échoués sont enregistrés à leur estimation, car certains échouent après que le fournisseur les a facturés. img2fig estimate --stages lookdev,turnaround,edit,modeldonne le prix d'une exécution complète. Ordre de grandeur typique : moins de 0,30 $ par appel image, 0,60 $ par modèle Tripo, environ 4 $ pour un bake-off à quatre fournisseurs. Les estimations sont prudentes ;cost_from_usage_usdsur les appels image est le chiffre basé sur les tokens.- Un bake-off (
--provider all) coûte environ sept exécutions Tripo. Ne le faites que si le propriétaire le demande ou si Tripo échoue clairement sur ce personnage.
Flux de travail
img2fig doctor # clés présentes ? Blender, ffmpeg trouvés ?
img2fig lookdev --ref personnage.png --description "..." # plan ; ajoutez --execute après approbation
img2fig turnaround --ref personnage.png --description "..." # utilise la dernière image look-dev
img2fig crop # views/view_{front,left,back,right}.png
img2fig edit --fix "Vue arrière : enlever la queue ronde sous le nœud ; jupe unie là." # seulement si nécessaire
img2fig crop # recadrer : prend la feuille ou l'édition la plus récente
img2fig model # Tripo, plan ; --execute après approbation
img2fig prep # orienter, normaliser, décimer, grader, rendus, compare.jpg
img2fig turntable # turntable/turntable.mp4
Toutes les commandes partagent --workdir DIR (par défaut $IMG2FIG_WORKDIR ou ./figure_work) ; les entrées par défaut sont le dernier fichier de l'étape précédente dans ce répertoire. Chaque commande imprime un objet JSON sur stdout ; lisez ok, les chemins, warning/warnings, next, et en cas d'échec error.type, error.message et error.detail (statut HTTP et corps du fournisseur, code de sortie et fin de stderr de Blender ou ffmpeg, chemin du journal).
Codes de sortie : 0 ok (y compris les exécutions à sec), 1 erreur fournisseur, 2 erreur d'utilisation, 3 budget dépassé, 4 clé/binaire/package manquant, 5 échec de Blender ou ffmpeg, 6 échec d'une vérification de résultat (la feuille ne s'est pas divisée en vues attendues), 7 bug interne.
Rédiger --description
Listez ce que la figurine doit conserver, en précisant les côtés du point de vue du personnage et du spectateur entre crochets : "pince à cheveux trèfle vert sur son côté GAUCHE (côté droit du spectateur dans la vue de face)". Décrivez ce que l'image de référence montre réellement, pas ce que vous avez l'intention de générer : les modèles d'image déplacent parfois un accessoire de l'autre côté, et la référence l'emporte.
Options de préparation importantes
--rot auto(par défaut) rend le modèle avec un ombrage plat à 0/90/180/270 degrés et compare chacun avecview_front.png. Si le résultat est ambigu, il revient à l'orientation connue du fournisseur (connue pour Tripo uniquement ; sinon, la sortie indique de vérifier le rendu de face). Passez--rot DEGpour remplacer.--grade matte(par défaut),light(tenues pâles : les blancs restent propres),dark(assombrit les tissus foncés),none.--keep-gloss 0.3conserve la rugosité et le métal d'origine sur les parties qui étaient brillantes dans la source.--blush=X,Z(répétable) peint un blush de joue doux à un point donné en fractions de figurine ; obtenez X,Z en mesurant la joue dansrenders/front.pnget en exécutantimg2fig point --x PX --y PY. Écrivez les valeurs négatives avec=(--blush=-0,08,0,6), sinon argparse les lit comme des options.--faces(par défaut 350000) limite le nombre de faces ; les textures normales et de couleur conservent les détails fins.
Pièges connus (tous observés)
- Le modèle d'image invente des détails, et le modèle 3D les construit. Un tourne-page a un jour gagné une queue pompon à l'arrière et un badge dans les poches de la veste que le personnage n'avait jamais eus ; le modèle 3D les a reproduits fidèlement. Corrigez cela au stade de l'image (
editavec un--fixpar problème, puiscropetmodelà nouveau). Ne corrigez pas le maillage. Une première édition peut laisser une autre invention derrière elle (le badge est devenu une décoration en forme de cupcake), alors comparez à nouveau après chaque édition. - Les petits détails sont flous. Chaque vue d'une feuille 3840x2160 ne fait qu'environ 1000 px de large, donc le visage d'une peluche ou les doigts ressortent flous dans le modèle. Une feuille plus grande n'est pas disponible ; jugez le rendu du visage et informez le propriétaire au lieu de promettre de petits détails nets.
- Les fournisseurs ne sont pas d'accord sur l'orientation. Les GLB de Tripo font face à +X après importation (nécessite -90 degrés). La vérification automatique le gère ; regardez quand même le rendu de face.
- Un grade entièrement mat tue les parties cristal et brillantes. Utilisez
--keep-glossou--grade nonelorsque le personnage a des parties en cristal, métal ou patent. - Les personnages procéduraux construits à la main n'atteignent pas la qualité de figurine. Un personnage modélisé à partir de primitives dans Blender n'a pas réussi à obtenir des cheveux organiques corrects ; le modèle image-3D l'a fait. Ne revenez pas à la modélisation procédurale pour les formes organiques.
- AgX vs Standard. Les rendus utilisent AgX par défaut : les hautes lumières ne sont pas écrêtées, mais les matériaux pâles et blancs deviennent grisâtres et moins saturés, c'est pourquoi les grades augmentent la saturation.
--view-transform standardcorrespond plus étroitement aux couleurs de référence mais écrête les zones lumineuses. La vérification d'orientation rend avec Standard pour que les couleurs se comparent équitablement. - sRGB vs linéaire dans Blender. La lecture des couleurs des pixels d'un PNG dans Blender (
Image.pixels) a renvoyé des valeurs sRGB encodées, pas linéaires. Décodez-les avant de les utiliser comme couleurs linéaires si vous étendez les scripts Blender.
Ressources et limites
- Les clés proviennent uniquement des variables d'environnement :
OPENAI_API_KEY(étapes image) etFAL_KEY(étape modèle). Ne les imprimez jamais et ne les écrivez pas dans des fichiers. - Blender en tant que binaire externe (testé sur 5.2 ; 4.2 ou plus récent devrait fonctionner) (
blenderdans PATH ouIMG2FIG_BLENDER) ; ffmpeg pour la tournante. - Le répertoire de travail contient les images, modèles et rendus générés du personnage du propriétaire. Ne les publiez, téléchargez ou ne les committez pas sauf si le propriétaire le demande ; traitez les personnages que le propriétaire a sous licence d'un tiers comme privés.
- Les invites sont dans
src/image_to_figure/prompts.py;--prompt-fileremplace un modèle pour un appel.
Impression 3D
img2fig print transforme un modèle (par défaut figure/figure_clean.glb ; tout GLB, STL, OBJ ou PLY avec --model ; avec --up auto, GLB/glTF/OBJ sont lus comme Y-up et STL/PLY comme Z-up) en un solide prêt à imprimer. Nécessite le module print (uv pip install -e '.[print]') ; installer pymeshlab également (GPL, pas une dépendance) ajoute un compte explicite des auto-intersections au rapport.
img2fig print --height 100 --base pedestal # solide, FDM ou résine
img2fig print --height 130 --base pedestal # FDM avec pièces fines : imprimez plus grand plutôt que d'épaissir
img2fig print --height 100 --base pedestal --hollow 2.0 # résine : paroi de 2 mm, trou(s) de drainage
img2fig print --model raw_tripo.glb --rot -90 --height 80 # un GLB Tripo brut fait face à +X
Terminé quand : la commande se termine par 0 et checks.printable est vrai (étanche, une 2-variété valide selon manifold3d, volume positif) ; checks.parts est 1 sauf si des pièces détachées ont été conservées intentionnellement ; checks.self_intersecting_faces est 0 lorsqu'il a été mesuré ; output.height_mm est égal à --height plus tout socle à moins d'un voxel près ; vous avez examiné print/figure_section.png (parois, cavité et trous de drainage) et les rendus figure_preview_*.png, et rapporté chaque entrée dans warnings, en particulier les pièces minces (checks.wall_thickness : thin_part_volume_fraction, largest_thin_parts avec leurs positions en mm ; relief_volume_fraction est un détail de surface fin, signalé mais jamais épaissi) et quoi faire à leur sujet. Si --thicken a été utilisé, vous avez comparé les rendus d'aperçu avec une exécution non épaissie et n'avez vu aucune nouvelle bosse sur le visage, les cheveux ou les accessoires ; sans Blender (pas d'aperçus), vérifiez que thicken.added_mm3 est du même ordre que wall_thickness_before.thin_part_volume_mm3 (les bosses apparaissent comme un volume ajouté bien au-delà) et regardez l'image de section.
Comment ça marche : la surface est voxélisée (voxel par défaut = hauteur / 500), les espaces sont scellés avec la plus petite fermeture morphologique qui enferme un intérieur (jusqu'à 8 voxels ; l'étape voxelize rapporte gap_closing_voxels) et l'intérieur est rempli, donc les bords ouverts, les coques qui se chevauchent et les auto-intersections disparaissent ; un champ de distance signé porte ensuite la coupe de base, le socle, l'évidement et les trous de drainage ; marching cubes, lissage Taubin et manifold3d produisent le maillage final. Les détails plus petits qu'environ un voxel sont perdus, et les parties plus proches que l'espace de fermeture fusionnent.
Options : --min-wall (par défaut 1,0 mm ; la résine peut descendre plus bas, le FDM veut généralement 1,2 ou plus) définit ce qui est considéré comme mince ; --thicken (désactivé par défaut) fait croître les parties minces jusqu'à cette épaisseur, voir ci-dessous ; --fragments merge|remove|keep avec --merge-gap (par défaut 2 mm) décide des parties flottantes : en mode merge, les parties dans l'espace sont attachées avec un pont et les plus éloignées sont conservées et signalées, jamais abandonnées silencieusement ; les miettes de moins de 1 mm3 sont toujours supprimées ; --base flat|pedestal|none ; --hollow WALL avec --drain-hole perce un trou par cavité par le bas (les poches de moins de 20 mm3 restent solides) ; --color écrit un PLY à couleur par sommet à partir de la texture du modèle pour les services couleur. Les STL et 3MF sont monochromes.
Pièces minces. Le rapport sépare les pièces minces (feuilles, ailettes, brins, rubans et cordons qui dépassent de plus de --min-wall d'un corps plus épais, avec les deux surfaces proches l'une de l'autre) du relief de surface (lignes en relief, bords de brins, petits points et bords convexes sur un corps épais). Pour le FDM, préférez imprimer plus grand : chaque pièce mince évolue avec la figurine (un ruban de 0,9 mm à 100 mm fait 1,17 mm à 130 mm), rien n'est remodelé, et la gestion des parois minces du slicer (parois Arachne, "detect thin walls") imprime la plupart de ce qui reste ; une fraction de pourcentage du volume sous la paroi est normale et acceptable. Utilisez --thicken lorsque la taille est fixe et que quelques pièces minces doivent être imprimées pleines (une boucle de ruban, une mèche, un cordon pendant, un ourlet de jupe) : il ne fait croître que les pièces minces, chacune jusqu'à environ --min-wall, et émousse leurs extrémités ; le relief n'est jamais épaissi. Lorsque des pièces minces subsistent après --thicken, l'avertissement le dit et suggère d'imprimer plus grand ou d'ajuster les paramètres du slicer, pas une autre exécution. Bords de la définition : le relief qui s'élève de plus de --min-wall du corps (une crête haute et étroite, un brin profondément en relief) compte comme une pièce mince et est émoussé ; une fine toile courte enjambant un espace entre deux parties épaisses (jusqu'à environ deux fois --min-wall de large) est signalée comme relief, et un slicer peut la laisser tomber et laisser un trou, alors vérifiez les toiles dans l'aperçu du slicer. La croissance se fait dans toutes les directions, donc --thicken allonge également légèrement les extrémités et peut fusionner des pièces minces plus proches que --min-wall.
Observé lors de la construction : le champ de distance binaire laisse des terrasses visibles à moins que le résultat ne soit lissé (Taubin, --smooth, par défaut 10 itérations, conserve le volume) ; projeter les sommets sur la surface source a plutôt replié les feuilles minces et a été abandonné. Le lissage et la simplification du maillage peuvent tous deux introduire des auto-intersections dans les régions minces ; la commande essaie moins de lissage et des tolérances plus serrées jusqu'à ce que la vérification soit propre et rapporte ce sur quoi elle s'est arrêtée (étape smooth_and_simplify). L'évidement doit laisser les poches non drainables solides, sinon elles deviennent des vides scellés. Sur une vraie figurine image-3D, deux pièces symétriques de 120 mm3 ont été modélisées comme des coques séparées à 1,3 mm du corps ; une version antérieure les a supprimées car elles se trouvaient juste au-delà d'un espace de fusion de 1 mm, c'est pourquoi les parties éloignées sont désormais conservées et signalées. Sur une vraie figurine de 100 mm avec --min-wall 1,2, un premier --thicken a couvert le visage, les cheveux, les nœuds et un accessoire en peluche de petites bosses rondes : il a traité tout ce qu'une boule de 1,2 mm ne pouvait pas atteindre comme mince, y compris le relief peu profond comme les bords de brins, les cils et points en relief, et a fait croître chacun de ceux-ci de 0,6 mm de chaque côté (5,5 % de volume en plus). Sans épaississement, la même...