Différences
Ci-dessous, les différences entre deux révisions de la page.
Prochaine révision | Révision précédente Prochaine révision Les deux révisions suivantes | ||
recherche:datamoshing:start [2019/12/03 09:24] gweltaz créée |
recherche:datamoshing:start [2019/12/20 12:53] gweltaz [Préparation] |
||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
====== Datamoshing ====== | ====== Datamoshing ====== | ||
+ | {{ :recherche:datamoshing:texture-10714.png?nolink&600 |}} | ||
+ | ===== La méthode "classique" ===== | ||
+ | ==== Préparation ==== | ||
+ | Le format ''.avi'' est le plus résilient, et donc le plus propice à la corruption. Sa structure est connue et il est plus facile de s'attaquer à un seul format de fichier plutôt que de vouloir tripatouiller tous les formats à l'aveugle. Il faudra donc convertir votre vidéo au format avi grâce à l'outil en ligne de commande ''ffmpeg''. | ||
+ | |||
+ | Sous Linux on peut l'installer avec la commande: | ||
+ | ''$ sudo apt install ffmpeg'' | ||
+ | |||
+ | ==== Transformation ==== | ||
+ | |||
+ | |||
+ | ==== Finalisation (Baking) ==== | ||
+ | |||
+ | |||
+ | ===== Et pourquoi pas en temps réel ? ===== | ||
+ | |||
+ | ==== Mode 1 ==== | ||
+ | Les pixels de couleur (l'image de fond) est mise-à-jour à intervalle régulière (définit par la constante ''REFRESH_INTERVAL'') et le masque de déplacement est mis-à-jour en continue. C'est le mode qui se rapproche le plus de l'effet "bloom" qu'on peut obtenir en datamoshing classique (par corruption de fichier avi). Pour obtenir un résultat au plus près de l'effet original, il faudrait calculer les vecteurs du masque de déplacement en fonction du déplacement réel des pixels d'une image à l'autre. On calculerait ainsi un P-Frame, qu'on viendrait ensuite appliquer sur notre image de fond. Par simplicité, dans le code ci-dessous, le masque du déplacement est calculé en fonction de la couleurs des pixels du flux vidéo. Le canal rouge définit le déplacement horizontal et le canal vert définit le déplacement vertical. | ||
+ | |||
+ | <accordion> | ||
+ | <panel title="Mode 1 (cliquer pour afficher le code)"> | ||
+ | <code java datamoshing_1.pde> | ||
+ | import processing.video.*; | ||
+ | |||
+ | // | ||
+ | // PARAMETERS | ||
+ | // | ||
+ | int REFRESH_INTERVAL = 14000; // in millisecs | ||
+ | float START_DISPLACEMENT = 0.0; | ||
+ | float SPEED = 1.0; | ||
+ | boolean INVERT_COLORS = false; | ||
+ | |||
+ | |||
+ | Capture video; | ||
+ | PVector[] vectorMap; | ||
+ | PImage display; | ||
+ | PImage source_img; | ||
+ | int source_x, source_y; | ||
+ | int index; | ||
+ | float amp; | ||
+ | int last_update; | ||
+ | |||
+ | |||
+ | void setup() { | ||
+ | size(1024, 768); | ||
+ | video = new Capture(this, width, height); | ||
+ | video.start(); | ||
+ | while (!video.available()) { | ||
+ | delay(100); | ||
+ | } | ||
+ | video.read(); | ||
+ | vectorMap = new PVector[video.pixels.length]; | ||
+ | updateDisplacementMap(vectorMap, video); | ||
+ | display = createImage(width, height, RGB); | ||
+ | source_img = video.copy(); | ||
+ | amp = START_DISPLACEMENT; | ||
+ | last_update = millis(); | ||
+ | } | ||
+ | |||
+ | |||
+ | void updateDisplacementMap(PVector[] vector_map, PImage map_img) { | ||
+ | map_img.loadPixels(); | ||
+ | float x_off, y_off; | ||
+ | for (int j=0; j<height; j++) { | ||
+ | for (int i=0; i<width; i++) { | ||
+ | index = i + width*j; | ||
+ | color displacementPix = map_img.pixels[index]; | ||
+ | // Use red channel for horizontal displacement | ||
+ | // and green channel for vertical displacement | ||
+ | x_off = -0.5 + (displacementPix >> 16 & 0xFF) / 255.0; | ||
+ | y_off = -0.5 + (displacementPix >> 8 & 0xFF) / 255.0; | ||
+ | vector_map[index] = new PVector(x_off, y_off); | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | void draw() { | ||
+ | if (video.available()) { | ||
+ | video.read(); | ||
+ | updateDisplacementMap(vectorMap, video); | ||
+ | if (millis() - last_update > REFRESH_INTERVAL) { | ||
+ | source_img = video.copy(); | ||
+ | source_img.loadPixels(); | ||
+ | last_update = millis(); | ||
+ | amp = START_DISPLACEMENT; | ||
+ | } | ||
+ | } | ||
+ | | ||
+ | index = 0; | ||
+ | for (int j=0; j<display.height; j++) { | ||
+ | for (int i=0; i<display.width; i++) { | ||
+ | source_x = round(amp * vectorMap[index].x + float(i)); | ||
+ | source_y = round(amp * vectorMap[index].y + float(j)); | ||
+ | while (source_x < 0) | ||
+ | source_x += display.width; | ||
+ | while (source_x >= display.width) | ||
+ | source_x -= display.width; | ||
+ | while (source_y < 0) | ||
+ | source_y += display.height; | ||
+ | while (source_y >= display.height) | ||
+ | source_y -= display.height; | ||
+ | | ||
+ | display.pixels[index] = source_img.pixels[display.width*source_y + source_x]; | ||
+ | | ||
+ | index++; | ||
+ | } | ||
+ | } | ||
+ | display.updatePixels(); | ||
+ | if (INVERT_COLORS) display.filter(INVERT); | ||
+ | |||
+ | image(display, 0, 0); | ||
+ | | ||
+ | amp += SPEED; | ||
+ | } | ||
+ | |||
+ | void mouseClicked() { | ||
+ | saveFrame("pic-###.png"); | ||
+ | } | ||
+ | </code> | ||
+ | </panel> | ||
+ | </accordion> | ||
+ | ==== Mode 2 ==== | ||
+ | Cette fois c'est le fond (les pixels de couleur) qui est continuellement mis-à-jour et le masque de déformation ne change que de temps en temps. Vous pouvez ajuster la fréquence de mise-à-jour du masque de déformation en modifiant la constante ''REFRESH_INTERVAL''. | ||
<accordion> | <accordion> | ||
Ligne 9: | Ligne 133: | ||
// PARAMETERS | // PARAMETERS | ||
// | // | ||
+ | int REFRESH_INTERVAL = 14000; // in millisecs | ||
float START_DISPLACEMENT = 800.0; | float START_DISPLACEMENT = 800.0; | ||
float SPEED = 2.5; | float SPEED = 2.5; | ||
- | boolean INVERT_COLORS = false; | + | boolean INVERT_COLORS = true; |
Ligne 33: | Ligne 158: | ||
video.read(); | video.read(); | ||
vectorMap = new PVector[video.pixels.length]; | vectorMap = new PVector[video.pixels.length]; | ||
- | captureVideoMap(vectorMap, video.copy()); | + | updateDisplacementMap(vectorMap, video); |
display = createImage(width, height, RGB); | display = createImage(width, height, RGB); | ||
source_img = video.copy(); | source_img = video.copy(); | ||
Ligne 41: | Ligne 166: | ||
- | void captureVideoMap(PVector[] vector_map, PImage map_img) { | + | void updateDisplacementMap(PVector[] vector_map, PImage map_img) { |
map_img.loadPixels(); | map_img.loadPixels(); | ||
float x_off, y_off; | float x_off, y_off; | ||
Ligne 47: | Ligne 172: | ||
for (int i=0; i<width; i++) { | for (int i=0; i<width; i++) { | ||
index = i + width*j; | index = i + width*j; | ||
- | color displacementPix = video.pixels[index]; | + | color displacementPix = map_img.pixels[index]; |
// Use red channel for horizontal displacement | // Use red channel for horizontal displacement | ||
// and green channel for vertical displacement | // and green channel for vertical displacement | ||
Ligne 60: | Ligne 185: | ||
if (video.available()) { | if (video.available()) { | ||
video.read(); | video.read(); | ||
- | if (millis() - last_update > 15000) { | + | if (millis() - last_update > REFRESH_INTERVAL) { |
// Update vectorMap | // Update vectorMap | ||
- | captureVideoMap(vectorMap, video.copy()); | + | updateDisplacementMap(vectorMap, video); |
last_update = millis(); | last_update = millis(); | ||
amp = START_DISPLACEMENT; | amp = START_DISPLACEMENT; | ||
} | } | ||
- | if (INVERT_COLORS) video.filter(INVERT); | ||
} | } | ||
| | ||
Ligne 89: | Ligne 213: | ||
} | } | ||
display.updatePixels(); | display.updatePixels(); | ||
+ | if (INVERT_COLORS) display.filter(INVERT); | ||
image(display, 0, 0); | image(display, 0, 0); | ||
| | ||
Ligne 100: | Ligne 225: | ||
</panel> | </panel> | ||
</accordion> | </accordion> | ||
+ | |||
+ | ===== Références ===== | ||
+ | Un outil libre et ouvert, écrit en python, pour appliquer différentes techniques de datamoshing à un fichier vidéo : | ||
+ | |||
+ | [[https://github.com/itsKaspar/tomato]] | ||
+ | |||
+ | Un tutorial complet (en anglais) sur la théorie et l'utilisation du logiciel Avidemux pour le datamoshing : | ||
+ | |||
+ | [[http://forum.glitchet.com/t/tutorial-make-video-glitch-art-how-to-datamosh-in-plain-english/36]] |