スケーラブルアート論
目次 |
概要
- 前提スキル
- 一年生の時にメディアプログラミング演習Iを履修し、基本的なProcessingのプログラミングができること。
- 不安な人は、以下の野口先生のメディアプログラミング演習Iのサイトで復習してください。https://r-dimension.xsrv.jp/classes_j/category/processing/
- 個人のPC(Windows、MacOSのどちらでもよい)に自分でProcessingの環境を構築できることが望ましい。
- 授業概要
インタラクティブアートは芸術を基盤として科学や工学を統合する新しい領域で、プログラミングなどのIT技術によって実現されます。プログラミングによって制作プロセスをアルゴリズム化した作品は、拡張性が高く(スケーラブル)、多様性を持たせることが容易です。これが、スケーラブルアートです。この授業では、その中でも、生物に見られる生成的(ジェネラティブ)な特徴をアートに応用したジェネラティブアートに関連する分野を扱います。その中には、人工生命、フラクタル、オートマトン、遺伝的アルゴリズム、ニューラルネットワークなどといったものが含まれます。 Processingプログラミングを使用して、スケーラブルな特徴を持つ作品を作成します。
- 到達目標
- スケーラブルアートについて理解し、応用例を作成できる。
- 生物の特徴と生物的なシステムについて理解する。
- Processingを使ってジェネラティブアートのプログラミングができる。
- 成績評価
確認テスト、課題、まとめテストで評価します。
- 参考資料
- 「数学から創るジェネラティブアート ―Processingで学ぶかたちのデザイン」(Generative Art with Math)
- 「The Nature of Code: Simulating Natural Systems with Processing」
- 英語PDF版は無料でダウンロードできます。https://wtf.tw/ref/shiffman.pdf
- 日本語PDF版を右のサイトで購入できます。https://www.borndigital.co.jp/book/5425.html
- ソースコードがGithubで公開されています。https://github.com/nature-of-code/
- Processingのチュートリアル Processing Tutorial
開発環境
開発環境として Processingを使用します。
開発環境については、以下を参照してください。
- https://processing.org/
- p5.js http://p5js.org
- ドットインストールp5.js入門 http://dotinstall.com/lessons/basic_p5js
- Generative Design with p5.js http://www.generative-gestaltung.de/
- Generative Art with Math https://www.openprocessing.org/user/57914
- Generative Design
生物と情報とアート
- 生物とは? 生物の特徴とは?
- 例:小石と貝殻
- 「生物と無生物の違いは何か?」説明してみよう。
- ゲノムのDNAマップ NCBI Genome Map Viewer
- ヒト一人を再生するのに必要な情報量は?
- 自己相似性、フラクタル
- 雪の結晶(0:25)
- 樹木(1:17)
- オウム貝(1:30)
- らせん、渦巻き状パターン
- 黄金角とフィボナッチ数列(3:00)
- ジェネラティブアート
- 自律性
- 予測不可能性
- パラメータ変形
- 偶発性
- 自己相似性
- 再帰性
- 対称性
- 周期性
- 双対性
- 抽象化と具体化
数学と力学の基礎
Nature of Code Chapter 1 Vector Git Processing
ベクトル
「Nature of Code」第1章の「1.1-1.6」pdf
- ベクトルを復習するための動画:高校数学Bベクトルの定義・成分
位置・速度・加速度
「Nature of Code」第1章の「1.7-1.10」pdf
- 動くボールの位置、速度、加速度はベクトルとして表すことができます。
- 速度は、位置の変化の割合、すなわち「次の位置=現在位置+速度」
- 秒速10m/sのボールの1秒後の位置=現在位置+10
- 加速度は、速度の変化の割合、すなわち「次の速度=現在速度+加速度」
- 自然落下運動の加速度は、重力加速度といい、9.8m/s2(秒の2乗)
- したがって、自然落下するボールの1秒後の速度=現在速度+9.8
- 重力加速度 国土地理院 「重力を知る」https://www.gsi.go.jp/buturisokuchi/grageo_gravity.html
トポロジー
- パックマン型2次元世界は、3次元ではトーラス(ドーナツ型)
- https://wakara.co.jp/mathlog/20200204
数学アート
矩形分割
フィボナッチ数列
らせん
整数の合同
コラッツ予想
人工生命(ALife)
セルオートマトン
ラングトンのアリ
レイノルズのボイド
反応拡散系
フラクタル
人工知能(AI)
Genetic Algorithm
Neural Networks
Processing Samples
音に反応する円
minimライブラリーをインストールする。
/** * Circles responding Sound Level */ import ddf.minim.spi.*; import ddf.minim.signals.*; import ddf.minim.*; import ddf.minim.analysis.*; import ddf.minim.ugens.*; import ddf.minim.effects.*; Minim minim; AudioInput in; void setup(){ size(500, 500); minim = new Minim(this); in = minim.getLineIn(Minim.STEREO, 512); background(0); } void draw(){ colorMode(RGB, 255); fill(0, 150); rect(-1, -1, width, height); colorMode(HSB, 360, 100, 100); float brightness = 50 + map(in.mix.level(), 0, 0.5, 0, 50); float hue = map(in.mix.level(), 0, 0.7, 0, 360); fill(hue, 100, brightness); float radious = 50 + map(in.mix.level(), 0, 0.5, 0, 100); int x = 250; int y = 250; ellipse( x, y, radious *2, radious * 2); } void stop(){ in.close(); minim.stop(); super.stop(); }
カメラ入力
Video|GStreamer-based video library for Processingライブラリをインストール。
- 使用可能なカメラのリスト出力
import processing.video.*; void setup(){ size(320, 240); String[] cameras = Capture.list(); for(int i=0; i<cameras.length; i++){ println("[" + i + "] " + cameras[i]); } }
- カメラ画像の出力
import processing.video.*; Capture cam; void setup(){ size(640, 480); String[] cameras = Capture.list(); for(int i=0; i<cameras.length; i++){ println("[" + i + "] " + cameras[i]); } cam = new Capture(this, cameras[1]); cam.start(); } void draw(){ if(cam.available() == true){ cam.read(); } image(cam, 0, 0); }
- 差分から動きを検出
import processing.video.*; int numPixels; int[] previousFrame; int noiseFilter = 50; Capture video; void setup() { size(640, 480); video = new Capture(this, width, height, 30); video.start(); numPixels = video.width * video.height; previousFrame = new int[numPixels]; loadPixels(); } void draw() { if (video.available()) { video.read(); video.loadPixels(); int movementSum = 0; for (int i = 0; i < numPixels; i++) { color currColor = video.pixels[i]; color prevColor = previousFrame[i]; //R, G, B int currR = (currColor >> 16) & 0xFF; int currG = (currColor >> 8) & 0xFF; int currB = currColor & 0xFF; // int prevR = (prevColor >> 16) & 0xFF; int prevG = (prevColor >> 8) & 0xFF; int prevB = prevColor & 0xFF; // int diffR = abs(currR - prevR); int diffG = abs(currG - prevG); int diffB = abs(currB - prevB); //noiseFilter if (diffR + diffG + diffB > noiseFilter) { movementSum ++; pixels[i] = color(currR, currG, currB); // //pixels[i] = 0xFF000000 | (currR << 16) | (currG << 8) | currB; } else { pixels[i] = color(0); } // previousFrame[i] = currColor; } updatePixels(); // println(movementSum); // } }
引力と加速度
「Nature of Code」第1章の「1.10 Interactivity with Acceleration」(p57)より。(一部改変)pdf
- 粒子はマウスポインタに引力で引き付けられれ、軌跡を残しながらマウスに近づく。
- 引力は、距離が近いほど、強くなる(反比例)。
- 速度には上限(topspeed)があり、引力と粒子の運動量(速度)が釣り合うと、マウスのまわりを回る惑星のような動きになる。
- Moverクラスの作成
- ベクトルPVectorを使い、location(位置)、velocity(速度)、acceleration(加速度)定義し、力学運動を記述している。
- 速度は、現在速度に加速度を加算 velocity.add(acceleration);
- 位置は、現在位置に速を加算 location.add(velocity);
Mover[] movers = new Mover[1000];//An array of objects void setup() { size(1000, 1000); smooth(); background(0); for (int i = 0; i < movers.length; i++) { movers[i] = new Mover();// Initialize each object in the array. } } void draw() { // background(0); fill(0,40); rect(0,0,width,height); for (int i = 0; i < movers.length; i++) { //Calling functions on all the objects in the array movers[i].update(); movers[i].checkEdges(); movers[i].display(); } } class Mover { PVector location; PVector velocity; PVector acceleration; float topspeed; Mover() { location = new PVector(random(width), random(height)); velocity = new PVector(0, 0); topspeed = 4.5; } void update() { //Our algorithm for calculating acceleration: //Find the vector pointing towards the mouse. PVector mouse = new PVector(mouseX, mouseY); PVector dir = PVector.sub(mouse, location); float magn = dir.mag(); dir.normalize();// Normalize. dir.mult(13 / magn ); // dir.mult(0.5);// Scale. acceleration = dir;// Set to acceleration. //Motion 101! Velocity changes by acceleration. Location changes by velocity. velocity.add(acceleration); velocity.limit(topspeed); location.add(velocity); } void display() {// Display the Mover // stroke(0); noStroke(); fill(250,255,100); ellipse(location.x, location.y, 10, 10); } void checkEdges() {// What to do at the edges if (location.x > width) { location.x = 0; } else if (location.x < 0) { location.x = width; } if (location.y > height) { location.y = 0; } else if (location.y < 0) { location.y = height; } } }
画像ファイルの結合
imagesフォルダにある画像_i000.pngから_i007.png(640*480)を縦2列、横4行に並べて結合する。
000 | 004 |
001 | 005 |
002 | 006 |
003 | 007 |
String folderName = "images"; String filePrefix = "_i"; int imageWidth = 640; int imageHeight = 480; int margin = 0; int imageNumX = 2; int imageNumY = 4; int imageNum = imageNumX * imageNumY; // X*Y int canvasWidth = imageNumX * imageWidth; int canvasHeight = imageNumY * imageHeight; PImage images[] = new PImage[imageNum]; void setup() { for (int i = 0; i < imageNum; i++) { images[i] = loadImage(folderName + "/" + filePrefix + nf(i, 3) + ".png"); } surface.setSize(canvasWidth, canvasHeight); noLoop(); } void draw() { background(255); for (int i = 0; i < imageNumX; i++) { for(int j = 0; j < imageNumY; j++){ image(images[i*imageNumY + j], imageWidth * i, imageHeight * j, imageWidth, imageHeight); } } save(folderName + "_combine.png"); exit(); }
配列のシャッフル
int[] nN = {0,1,2,3,4,5,6}; for(int i=(nN.length - 1); i>0; --i) { int j = (int)random(i+1); int tmp = nN[i]; nN[i] = nN[j]; nN[j] = tmp; }
クラスオブジェクトのソート
- バブルソート
rectsをメンバlevelの値の小さい順にソートする。
Kurasu[] rects = new kurasu[100]; for(int j=0; j < rects.length - 1; j++){ for(int i=0; i < rects.length - 1; i++){ if(rects[i].level > rects[i+1].level){ Kurasu tmp = rects[i+1]; rects[i+1] = rects[i]; rects[i] = tmp; } } } class Kurasu{ int index; int level; }
リンク
素数のグラフィック http://www.datapointed.net/visualizations/math/factorization/animated-diagrams/?infinity