Movie2Gcode
copier un film avec une imprimante 3D
Contributeur·ice·s
Statut du projet
Prototype
Statut de la publication
License
CC-by-sa-3.0
Inspiration
Fichiers source
Machines
Matériaux
Lien
Résumé
à l'occasion du travail de la semaine à la fabacademy, je dois concevoir un programme qui interface un ordinateur avec un capteur ou un actionneur.
J'ai choisi de finaliser un projet qui me tiend à coeur : copier un film avec une imprimante 3D
principe de fonctionnement
Un film est décomposé en photogrammes qui sont induviduellement :
- vectorisés
- transformé en STL
- compilé en GCode
à la fin les Gcodes sont empilés, de manière à obtenir un objet 3D dont chaque couche est un photogramme du film.
Le résultat est une décomposition spaciale du mouvement.
problèmes rencontrés
Le point dur est le passage en 3D.
Il existe dans fabmodules gif_stl qui transforme un gif en stl exactement sur ces modalités.
Hélas, il produit des trous dans le maillage résultant (j'ai l'impression que ça correspond aux endroits où les couches n'ont pas le même nomre de pixels pleins).
Ce défaut n'est pas trop grave pour un objet relativement petit, mais pour un film contenant plusieurs centaines d'images, cela provoque un travail de postproduction long et compliqué.
J'ai donc envisagé d'utiliser openscad pour transformer les images en STL.
Mon but initial était de réaliser un STL global de tout le film.
Hélas, openscad utilise beaucoup de ressources, particulièrement pour extruder des dxf. Je n'ai pas réussi à faire un calcul dans des temps raisonnables.
Finalement, je suis arrivé à une solution : openscad réalise un STL par image, puis je calcule le Gcode. à la fin, je compile tous les gcodes pour obtenir un fichier de fabrication complet.
Ce résultat a une caractéristique amusante : je construit un objet 3D sans jamais avoir de maillage global de l'objet, mais j'obtiens quand même un objet réel.
le programme
Comme la chaîne de conversion utilise de nombreux programmes, j'ai réalisé un premier programme en bash :
extraction des images fixes
avec ffmpeg :
fmpeg -i RaceHorseMuybridge.flv images/image-%3d.bmp
le reste des transformations se réalisent en boucle pour chaque image
boucle de traitement
function demon(){
echo "traitement de toutes les images image-$1*.bmp"; for i in image-$1*.bmp; do
if [ -f ${i} ] then echo "_________________________________________________________${i}";
potrace -o ${i%bmp}eps -k 0.6 -t 50 -B-0.25 -e ${i}; #potrace -o ${i%bmp}eps -k 0.43 --tight -M -0.41 -e ${i}; pstoedit -dt -f dxf:-polyaslines ${i%bmp}eps ${i%bmp}dxf; rm ${i%bmp}eps #ecrit le fichier openscad echo "intersection(){ translate([-4,0,-5])cube([96,63,10]);scale([15,15,1])linear_extrude(height = 0.15, center = false, convexity = 10) import (file = \"${i%bmp}dxf\");}translate([-4,0,0])cube(0.05); translate([91.95,62.95,0])cube([0.05,0.05,0.14]);" > ${i%bmp}scad; echo "calcul du ${i%bmp}STL"; /home/cedric/soft/openscad/openscad -o ../stl/${i%bmp}stl ${i%bmp}scad; rm ${i%bmp}scad; rm ${i%bmp}dxf; echo "_______________________________________${i%bmp}STL ok";
else echo ${i} existe -----------------pas; fi
done
}
vectorisation
Pour définir du plein et du vide à partir d'images en valeurs de lumière, je vectorise les images avec potrace
potrace -o ${i%bmp}eps -k 0.6 -t 50 -B-0.25 -e ${i};
openSCAD n'accepte que le format DXF, et potrace en produit, mais une variante non lisible par openSCAD
Je suis donc passé par le format EPS, transformé ensuite en DXF via pstoedit
pstoedit -dt -f dxf:-polyaslines ${i%bmp}eps ${i%bmp}dxf;
création du STL
pour chaque image, je construit un STL à l'aide d'openscad :
intersection(){
translate([-4,0,-5])cube([96,63,10]); scale([15,15,1]) linear_extrude(height = 0.15, center = false, convexity = 10) import (file = "${i%bmp}dxf");
}translate([-4,0,0])cube(0.05); translate([91.95,62.95,0]) cube([0.05,0.05,0.14]);
le fichier est alors rendu pour produire le STL
openscad -o ../stl/${i%bmp}stl ${i%bmp}scad;
multithread quick and dirty
Openscad est assez long à calculer les STL (avec le cheval de muybridge, environ 20sec/image), de plus il n'est pas optimisé pour les multicoeurs.
Pour profiter quand même de toutes les capacités des mon ordinateur et réduire le temps de calcul, j'ai réalisé une fonction multitâche , simplement grâce à l'option "&" des commandes consoles.
for z in {0..4}
do
echo ${z}1;
##lance trois demons sur différentes parties des images
demon ${z}0& demon ${z}1& demon ${z}2& demon ${z}3; echo "premiere fournee finie=====================================================" demon ${z}4 & demon ${z}5& demon ${z}6; echo "seconde fournee finie=====================================================" demon ${z}7 & demon ${z}8& demon ${z}9; echo "troisieme fournee finie=====================================================" done
cette boucle traite jusqu'à 500 images avec un ordinateur 4 coeurs
et permet donc de diviser par 4 le temps de calcul global.
calcul des Gcodes
ils sont réalisés avec Slic3r
comme ce dernier est multicoeur, je n'ai pas intégré ce traitement dans la boucle principale
for i in image-*.stl;
do
- calcul slicer
slic3r --load ../config.25.plein.ini -o ../gcodes/${i%stl}gcode ${i} echo ${i}; done python mixGcode.py
La dernière commande (mixGcode.py) appelle un script qui compile tous les Gcodes ensemble, en conservant que l'ente et le pied du premier, en ajoutant un ofset correspondant à l'épaisseur des couches.
Résultat
J'ai testé le programme avec le cheval de Muybridge.