lecture:design_with_prototyping:processing編:12.動画の再構成

動画像の再構成(ピクセルの応用)

では次に動画ピクセルを再構成する方法を考えてみましょう.まずは動画ファイルを読み込んで,再生する だけのプログラムを書いてみます.下記の動画をサンプルとして保存してください.ダウンロードしたファイルはdataフォルダに置くことを忘れないようにして下さい.また,Processingのメニューに ある「Sketch」→「Import Library..」からvideoのライブラリを追加することで,import processing.video.*;を自動で プログラムの頭に追加できます.下記にサンプルビデオを置いておきますので、適時利用してください。なお女性の動画はVideo by Tim Savage from Pexelsにて公開されています。

この他にも pexels.comに行くと無料で利用できる高画質動画があるので、好きなものを使っていきましょう。

最初のサンプルを動かすまでの流れを以下の動画にまとめてました.

03_sample01.pde
import processing.video.*;
 
Movie mov;
void setup()
{
  size(640, 360);
  noStroke();
  mov = new Movie(this, "sample.mp4");
  mov.noLoop();
  mov.play();
}
void draw()
{
  background(0);
  if( mov.available() == true ){
    mov.read();
    mov.loadPixels();
  }
  image(mov, 0,0, width, height);
}

では次に各画素の色情報を取得してみましょう. 色情報は静止画像と同じように get(int x, int y)メソッドを用いて参照することができます.

03_sample02.pde
import processing.video.*;
 
Movie mov;
void setup()
{
  size(720, 406);
  noStroke();
  mov = new Movie(this, "sample.mp4");
  mov.noLoop();
  mov.play();
}
void draw()
{
  background(0);
  if( mov.available() == true ){
    mov.read();
    mov.loadPixels();
  }
 
  for( int i = 0; i < mov.height; i++ ){
    for( int j = 0; j < mov.width; j++ ){
      stroke(mov.get(j,i));
      point(j,i);
    }
  }
}

どうでしょう?...動きはしますが,めちゃめちゃカクカク(フレームレートが小さい)していると思います. ちなみにProcessingのサイトでは,

You want your sketch to run faster! P2D and P3D make use of OpenGL-compatible graphics hardware. In other words, some of the work required to draw all the pixels in the window can happen on your computer's graphics card which is often more effecient. Keep in mind that OpenGL is not magic pixie dust that makes any sketch faster (though it's close), you will also need to carefully consider the techniques you are using to do the drawing as well. In particular, using the new “shape recording” functionality available in PShape (see PShape tutorial) can greatly increase speed in P3D mode.

と記載されており,P2Dを指定すればハードウェアレンダリングで描画がもう少し早くなります.しかし今回のサンプルではP2Dではmovクラスからgetメソッドからの戻り値が正しい値を返さないため,CPU処理のみ(P2DやP3Dを指定しない)での描画例となっています.とりあえず馬場の環境では1fpsでないくらいでした.実際に描画する際はimage等の関数を利用したり,ピクセル数を減らして描画していきましょう.動画ファイルの場合, 一般的には一秒間に30コマの静止画がある為,静止画と同じように扱うと,Processingでは処理落ちしてしまいます. なので,そこで,point関数を使わず,直接movクラス内のピクセルを変更することで,動画像ピクセルを操作していきます.

静止画と同様にget関数でcolorクラスを取り出し,ネガポジ反転させたイメージを描画してみます.

03_sample03.pde
import processing.video.*;
 
Movie mov;
void setup()
{
  size(720, 406);
  noStroke();
  mov = new Movie(this, "sample.mp4");
  mov.noLoop();
  mov.play();
}
void draw()
{
 background(0);  
 if( mov.available() == true ){
   mov.read();
   mov.loadPixels();
   for( int i = 0; i < mov.height; i++ ){
     for( int j = 0; j < mov.width; j++ ){
       color c1 = mov.get(j,i);
        color c2 = color(255-red(c1), 255-green(c1), 255-blue(c1));
        mov.set(j,i,c2);
     }
   } 
   }
  image(mov, 0,0, mov.width, mov.height);
}

得られた画像ピクセルを静止画と同様に二値化を行い,それを表示するプログラムを記述して下さい.下に記述しますが,filterメソッドを使うと簡単です.filterメソッドはPImageのメソッドになっているので,https://processing.org/reference/PImage_filter_.htmlを参照して,いくつかのfilterの種類を試してみましょう.

03_sample04.pde
import processing.video.*;
 
Movie mov;
void setup()
{
  size(720, 406);
  noStroke();
  mov = new Movie(this, "sample.mp4");
  mov.noLoop();
  mov.play();
}
void draw()
{
 background(0);  
 if( mov.available() == true ){
   mov.read();
   mov.loadPixels();
   for( int i = 0; i < mov.height; i++ ){
     for( int j = 0; j < mov.width; j++ ){
       color c1 = mov.get(j,i);
        color c2 = color(red(c1), green(c1), blue(c1));
        mov.set(j,i,c2);
     }
   }
 }
  mov.filter(THRESHOLD, 0.5);
  image(mov, 0,0, mov.width, mov.height);
 
}

静止画の再構成で実践したように、ピクセルを大きくして描画してみます。各ピクセル座標にはすでにアクセスできるので、これを間引いてまずはアクセスします。以下の例では10ピクセルごとにそれぞれ縦横のピクセル情報を直径10の円で表現しています。これを四角にしてもう少し画素を大きくすればプライバシー保護などで利用されるモザイク表現になることがわかると思います。

sample05.pde
import processing.video.*;
 
Movie mov;
void setup()
{
  size(640, 360);
  noStroke();
  mov = new Movie(this, "sample.mp4");
  mov.loop();
  mov.play();
}
 
void draw()
{
  if ( mov.available() == true ) {
    background(0); 
    mov.read();
    mov.loadPixels();
    for ( int i = 0; i < mov.height; i=i+10 ) {
      for ( int j = 0; j < mov.width; j=j+10 ) {
        color c1 = mov.get(j, i);
        fill(c1);
        ellipse(j, i, 10, 10);
      }
    }
  }
}

では次は、一旦各ピクセルから明るさ情報を取り出した後、その明るさの値から描画する円の大きさにパラメータを渡すプログラムに変更します。上記でやった二値化変換とモザイクをあわせた表現です。明るさはそのままの計算だと0-255の範囲になるので、どのあたりに正規化したら面白いのかを tweak を用いて調整してみるとよいでしょう。

sample06.pde
import processing.video.*;
 
Movie mov;
void setup()
{
  size(640, 360);
  noStroke();
  mov = new Movie(this, "sample.mp4");
  mov.loop();
  mov.play();
}
 
void draw()
{
  if ( mov.available() == true ) {
    background(0); 
    mov.read();
    mov.loadPixels();
    for ( int i = 0; i < mov.height; i=i+20 ) {
      for ( int j = 0; j < mov.width; j=j+20 ) {
        color c1 = mov.get(j, i);
        float gray = (red(c1)+green(c1)+blue(c1))/3.0;
        gray = map(gray, 0,255, 0, 28);
        fill(255);
        ellipse(j, i, gray, gray);
      }
    }
  }
}

下記サンプルは5ピクセルごとに線を引き,各頂点の明るさに応じてy座標を少しずらしています.描いてるのはたった100本程度の線ですが,私たちはこれをみて人間がいることがわかります。このように線を描く,四角や三角,丸などの基本図形を用いて,動画データを再構成してみましょう.表示結果に失敗はありません.どのようなプログラムがどのような表現に結びつくのかを楽しみならが学んでください.

sample07.pde
import processing.video.*;
 
Movie mov;
void setup()
{
  size(640, 360);
  noStroke();
  mov = new Movie(this, "sample.mp4");
  mov.loop();
  mov.play();
}
void draw()
{
 
  noFill();
  if ( mov.available() == true ) {
    background(0);  
    mov.read();
    mov.loadPixels();
    for ( int i = 0; i < mov.height; i=i+5 ) {
      beginShape();
      for ( int j = 0; j < mov.width; j++ ) {
        color c1 = mov.get(j, i);
        stroke(255);
        strokeWeight(1);
        vertex(j, i-(red(c1)+green(c1)+blue(c1))/9);
      }
      endShape();
    }
  }
}

静止画同様に、アスキーアートで動画を描いてみましょう。ここではサンプルコードを載せないので、静止画のページを参照して自分で作ってみてください。

練習

ここまでの内容をベースにして、自分だけの動画エフェクトを制作してみましょう。

作品ギャラリー

  • /home/users/2/lolipop.jp-4404d470cd64c603/web/ws/data/pages/lecture/design_with_prototyping/processing編/12.動画の再構成.txt
  • 最終更新: 2021/02/27 17:55
  • by baba