====== 動画像の再構成(ピクセルの応用)======
では次に動画ピクセルを再構成する方法を考えてみましょう.まずは動画ファイルを読み込んで,再生する だけのプログラムを書いてみます.すでに以下のリンクにテンプレートを用意していますので、まずはp5 Editorで開いて実行してみましょう。
ブラウザのセキュリティ設定により、動画が自動的に再生されない(キャンバスが真っ白だったり真っ黒だったりする)場合は、ユーザが明示的に操作して一度だけ動画を再生して上げる必要があります。以下のコードを追加して、実行した後にキーボード入力を行い、明示的に動画再生を行うことで解決できます。一度再生できれば次からは自動で再生されます。
function keyPressed(){
video.play();
}
* テンプレート:https://editor.p5js.org/tetsuakibaba/sketches/IDkf4kxVw
実行をして以下の動画が再生されることを確認してください。
{{ :lecture:design_with_prototyping:p5.js編:video.mp4 |Pexelsのcottonbroによる動画}}
/*
Pexelsのcottonbroによる動画を利用しています:https://www.pexels.com/ja-jp/video/3205917/
*/
let video;
function setup() {
createCanvas(640, 360);
video = createVideo('video.mp4');
video.loop();
video.hide(); // html要素を隠す為
}
function draw() {
background(0);
video.loadPixels();
image(video, 0,0);
}
===== 各画素の取得 =====
では静止画と同様に各画素の色データを取得しました。video.get(x,y);ってな感じで取得できます。しかし、実行していただけるとわかると思いますが、実はめちゃくちゃ実行速度が遅くなります。この get() メソッド(関数)の実行速度が激遅なので、直接画素データにアクセスして各r,g,bの値を取得するようにコードを書き換えます。また実行速度が遅くなりすぎないように、1ピクセルずつ描画せず、10ピクセルごとの描画にしておきます。
/*
Pexelsのcottonbroによる動画を利用しています:https://www.pexels.com/ja-jp/video/3205917/
*/
let video;
function setup() {
createCanvas(640, 360);
video = createVideo('video.mp4');
video.loop();
video.hide(); // html要素を隠す為
}
function draw() {
background(0);
video.loadPixels();
for (let y = 0; y < height; y += 20) {
for (let x = 0; x < width; x += 20) {
const i = y * width + x;
const c = video.get(x,y);
let radius = 20;
fill(c);
ellipse(x,y,radius, radius);
}
}
}
どうでしょう?...動きはしますが,めちゃめちゃカクカク(フレームレートが小さい)していると思います.
というわけで、次のようにプログラムを修正します。
const c = video.get(x,y);
を
const i = y * width + x;
color(video.pixels[i * 4], video.pixels[i*4+1],video.pixels[i*4+2]);
に変更して、実行し直してみましょう。スムーズに動画が再生されることを確認してください。
===== 二値化変換 =====
得られた画像ピクセルを静止画と同様に二値化を行い,それを表示するプログラムを記述して下さい.下に記述しますが,filterメソッドを使うと簡単です.
{{ :lecture:design_with_prototyping:p5.js編:12-sample_threshold.png?nolink |}}
let video;
function setup() {
createCanvas(640, 360);
video = createVideo('video.mp4');
video.loop();
video.hide(); // html要素を隠す為
}
function draw() {
background(0);
video.loadPixels();
image(video, 0,0);
filter(THRESHOLD);
}
===== ドットで描く =====
静止画の再構成で実践したように、ピクセルを大きくして描画してみます。各ピクセル座標にはすでにアクセスできるので、これを間引いてまずはアクセスします。以下の例では10ピクセルごとにそれぞれ縦横のピクセル情報を直径10の円で表現しています。これを四角にしてもう少し画素を大きくすればプライバシー保護などで利用されるモザイク表現になることがわかると思います。
{{ :lecture:design_with_prototyping:p5.js編:12-mozaic.png?nolink |{{ :lecture:design_with_prototyping:p5.js編:12-mozaic.png?nolink |}}}}
let video;
function setup() {
createCanvas(640, 360);
video = createVideo('video.mp4');
video.loop();
video.hide(); // html要素を隠す為
ellipseMode(CORNER);
}
function draw() {
background(0);
video.loadPixels();
for (let y = 0; y < height; y += 20) {
for (let x = 0; x < width; x += 20) {
const i = y * width + x;
const c = color(video.pixels[i * 4], video.pixels[i*4+1],video.pixels[i*4+2]);
let radius = brightness(c);
radius = 20;//map(radius, 0, 255, 0,40);
fill(c);
ellipse(x,y,radius, radius);
}
}
}
===== 明るさを円の大きさで描く =====
では次は、一旦各ピクセルから明るさ情報を取り出した後、その明るさの値から描画する円の大きさにパラメータを渡すプログラムに変更します。上記でやった二値化変換とモザイクをあわせた表現です。
let video;
function setup() {
createCanvas(640, 360);
video = createVideo('video.mp4');
video.loop();
video.hide(); // html要素を隠す為
ellipseMode(CORNER);
}
function draw() {
background(0);
video.loadPixels();
for (let y = 0; y < height; y += 20) {
for (let x = 0; x < width; x += 20) {
const i = y * width + x;
const c = color(video.pixels[i * 4], video.pixels[i*4+1],video.pixels[i*4+2]);
let radius = brightness(c);
radius = map(radius, 0, 255, 0,40);
fill(255);
ellipse(x,y,radius, radius);
}
}
}
{{:lecture:design_with_prototyping:p5.js編:may-18-2021_13-12-16.gif|}}
===== 明るさを線で描く =====
下記サンプルは5ピクセルごとに線を引き,各頂点の明るさに応じてy座標を少しずらしています.描いてるのはたった100本程度の線ですが,私たちはこれをみて人間がいることがわかります。このように線を描く,四角や三角,丸などの基本図形を用いて,動画データを再構成してみましょう.表示結果に失敗はありません.どのようなプログラムがどのような表現に結びつくのかを楽しみならが学んでください.
let video;
function setup() {
createCanvas(640, 360);
video = createVideo('video.mp4');
video.loop();
video.hide(); // html要素を隠す為
ellipseMode(CORNER);
}
function draw() {
background(0);
video.loadPixels();
for (let y = 0; y < height; y += 5) {
beginShape();
for (let x = 0; x < width; x += 5) {
const i = y * width + x;
const c = color(video.pixels[i * 4], video.pixels[i*4+1],video.pixels[i*4+2]);
stroke(255);
noFill();
vertex(x, y + map(brightness(c), 0,255, 0,20));
}
endShape();
}
}
{{:lecture:design_with_prototyping:p5.js編:may-18-2021_13-13-23.gif|}}
===== アスキーアートで描く =====
静止画同様に、アスキーアートで動画を描いてみましょう。ここではサンプルコードを載せないので、静止画のページを参照して自分で作ってみてください。
{{ :lecture:design_with_prototyping:p5.js編:12_ascii_art.gif?nolink |}}
課題:ここまでの内容をベースにして、自分だけの動画エフェクトを制作してみましょう。
===== 技術小話(canvasで描いた内容を動画で保存する) =====
作ったエフェクトを課題等で動画形式に変換して提出する場合,chromeブラウザで動作させているのであれば,webm形式で保存するのが簡単です.以下のページにtemplateがあります.
* [[p5js:tips:canvasの動画保存|canvasを動画で保存する]]
ただし上記ファイルは p5canvasRecording.jsという別ファイルを読み込んでいるので,一旦作ってしまった課題ファイルとガッチャンコするのは初学者の場合は少し大変かなとおもいました.そこで,このページの課題を動画形式にで保存するための雛形も合わせて準備しておきました.「自作エフェクトを動画で提出しなきゃ」という場合は以下のtemplateを利用してください.
* https://editor.p5js.org/tetsuakibaba/sketches/BzKOpCCqr
テンプレートを利用して保存した動画ファイルの例を以下に示します.現時点(2021年5月19日)ではGoogleの独自形式なため,FirefoxやSafariでは再生できないことにご注意ください.このページをChromeブラウザで開いている場合に以下の動画を閲覧できます.
{{ :lecture:design_with_prototyping:p5.js編:newvid_3_.webm |}}
====== 作品ギャラリー ======
課題提出物を一部抜粋してご紹介します.