AfterEffectsでジェネラティブアートを作成してみた
とうとう訳のわからないものが来ました。
それもそのはず、こちらの作品はAfterEffectsのみではなくプログラミングを用いて制作しています。
使用したプログラミング言語は、ジェネラティブアートでよく使用されるProcessingという言語です。
基本はJavaなので覚えやすかったです。
今回の記事はほぼProcessingの解説になると思いますので、プログラミングやジェネラティブアートに全く興味がない人は申し訳ございません。
今回の動画
ジェネラティブアートとは?
解説の前に、ジェネラティブアートって一体何なんでしょうか。
ジェネレーティブアートまたはジェネラティブアート(英: Generative Art)は、コンピュータソフトウェアのアルゴリズムや数学的/機械的/無作為的自律過程によってアルゴリズム的に生成・合成・構築される芸術作品を指す。
出典: フリー百科事典『ウィキペディア(Wikipedia)』
だそうです。
私も詳しくは分かっていませんが、プログラミングや計算式などで生み出されるアートのことだと思っています。
なので今回の作品も立派なジェネラティブアートです!
作品の解説
解説とは言いますが、さすがにProcessingの解説をするには私自身の知識量もまだまだ未熟ですので、とりあえず動いたソースコードを紹介する程度に留めておきます。
まずは制作の流れの紹介です。
1.AfterEffectsでモーションを作る
2.モーションを動画に書き出す
3.Processingで動画を読み込み、文字に変換する処理をし、連番で書き出す
4.連番をAfterEffectsで動画にする
ジェネラティブアートと言っておきながら、基となるモーションはAfterEffectsで作っています。
Processingでは輪郭を検出して文字を配置するという処理を行っています。
そのため、AfterEffectsで作ったモーションはこんな感じです。
なぜ輪郭なのかというと、単純に私のProcessingスキル不足です。この作品を作る前日に初めて触りました……。
Processingの処理の紹介をします。
import processing.core.*;
import processing.video.*;
import processing.opengl.*;
import com.jogamp.opengl.GL2;
import gab.opencv.*;
import controlP5.*;
Movie movie;
OpenCV cv;
PFont font;
int sn;
String[] st = {"も", "ー", "し", "ょ", "ん", "ぐ", "ら", "ふ", "ぃ", "っ", "く", "す"};
int time;
ArrayList<Contour> contours;
void setup() {
size(1080, 1080, P2D);
pixelDensity(displayDensity());
frameRate(1);
movie = new Movie(this, "f1.mov");
movie.loop();
movie.play();
movie.speed(1);
font = loadFont("YuMincho-Regular-48.vlw");
sn = 0;
cv = new OpenCV(this, 1080, 1080);
}
void draw() {
update();
if (time == 15) {
time = 0;
}
time++;
//saveFrame("frames/####.png");
}
void update() {
background(255);
cv.loadImage(movie);
cv.findCannyEdges(50, 150);
contours = cv.findContours();
for (Contour contour : contours) {
stroke(255, 0, 0);
for (PVector point : contour.getPoints()) {
if (point.x % 6==0 && point.y % 5==0) {
vertex(point.x, point.y);
fill(0);
textFont(font);
textAlign(CENTER);
textSize(random(20, 30));
text(st[int(random(st.length))], point.x, point.y);
}
if (point.x % 30==0 && point.y % 28==0) {
vertex(point.x, point.y);
fill(0);
textFont(font);
textAlign(CENTER);
textSize(random(50, 60));
text(st[int(random(st.length))], point.x-5, point.y+5);
}
}
}
}
void movieEvent(Movie m) {
m.read();
}
ソースコードそのまま貼りつけの状態で申し訳ないのですが、これだけで動きます!
f1.movというのがAfterEffectsで作ったモーションの動画です。
framerateが1になっているのは、リアルタイム(30fps)ですと1080×1080のサイズにしたときに処理が追い付かなかったため、1フレームに1秒かけて処理しています。
AfterEffectsで書き出したモーションも5秒のモーションを1fpsで書き出しています。(150フレーム→150秒の動画)
そのため、必然的にProcessingでの文字変換処理に2分30秒かかることになります!
レンダリングの仕組みは分かっていませんが、こういうことなんでしょうか。
連番での書き出しはsaveFrameで行っています。(今はコメントアウトされています)
肝心の輪郭検出部分についてですが、輪郭は点で検出されているようで、その数はかなり膨大です。
その点一つ一つに文字を配置すると、画面が真っ黒になってしまいます。そして非常に重いです。
そのため点の位置を揃える意味合いもかねて点を座標で厳選しています。
具体的には、点のx座標が6で割れる、かつy座標が5で割れる点の位置に小さめの文字を配置しています。
そして、点のx座標が30で割れる、かつy座標が28で割れる点の位置に大きめの文字を配置しています。
これ以外にも検出される点の数を減らす方法はあると思いますが、こうすることで文字をある程度整列して配置することが出来ます。
あとは連番をAfterEffectsで読み込んで、軽く色をつけたり遊んでみたりするだけです。
繰り返しますが、Processingはこの作品を作る前日と当日の2日しか触っていないので、ソースコードの汚さはもちろん、そもそも記述が適切でない可能性が十分あります。
参考にする際はご注意ください!
かなり実験的な作品でした。改めて考えてもあまりジェネラティブアートじゃないですね……。
ちゃんとしたジェネラティブアートを作るにはProcessingの勉強はもちろん、数学の知識も必要になりそうなので、習得はまだまだ先になりそうです。
普段のモーショングラフィックスにもうまく取り入れられたら面白いと思うので、活用していきたいと思います。
今回の紹介は以上です!
ここまでお読みいただきありがとうございました。