(多分)世界初の宙玉レンズ風エフェクト動画生成ソフトを作ったので公開

はじめに

 以前「宙玉レンズを作った次の日に無料の宙玉レンズiPhoneアプリが出たからむしゃくしゃしてProcessingで宙玉レンズソフト作って、後悔はしていないので公開しました」そのとき、今後のところに

気が向いたらもうちょっと改良します。後は、多分1時間くらい頑張れば動画の宙玉レンズ風エフェクトもできるようになるはずなので気が向いたら作ります。でも多分気は向かないと思います。万一欲しい人がいたらリクエストして下さい。

 と書いていたのですが、驚く事に熱いリクエストが多数あったので動画ソフトを公開しました。

 1件だけだし!でも、私は約束を破らないことで定評のある社会人なのでちゃんと約束はまもりますよ、というわけで公開します。グーグルで宙玉レンズの動画を作るソフトを適当に検索した感じ出てこなかったので、勝手に世界初を名乗ります。誰かに指摘されるまで優越感に浸りたいと思います。いずれiPhoneでも宙玉レンズ動画ソフトでるかなと思っていますが、そのときは「私の方が先だ!」と優越感たっぷりに見下してやりたいと思います☆

成果物

 というわけで、社会人らしく成果から報告します。私は会社のイヌだワン☆

 どう?動画にすると結構いい感じじゃないですかね?ちょっと宙玉の位置がズレないのがうそっぽいですが、どんなレンズで撮った写真も宙玉レンズ風にできるのがよい点ですね。
 ちなみに動画はカメラOLYMPUS OM-D E-M5、レンズMZD 45mm f1.8の組み合わせで車に置いて撮影したものです。BGMは、適当なフリー素材が見つからなかったので、仕方なくiPadでGaragebandとKorg iKaossilatorの組み合わせでiPadだけでつくりました。ちなみに、BGM作る際に、iPad+Garageband+Korg iKaossilatorの組み合わせで誰でも機械的に無限に作曲出来る方法を編み出してしまったので興味ある人がいたらこれも公開します。社会人なので嘘つきません。

ソースコードと使い方

 ソースコードです。いつもの通りProcessingというプログラミング言語を使っています。Processingダウンロードして(2.xx系でなく1.xx系のバージョン使って下さい)ソースコピペしてRUN押せばWinでもMacでも動くと思います。
 特にプログラムの説明はないので適当に読み解いて下さい。前回の宙玉レンズソフトをちょちょいと弄って動画にしただけです。正方形でも横長の動画でも大丈夫です。縦長はダメなので必要な人は適当に弄って下さい。あと、ちょっと宙玉っぽく見えるように微妙に改良しています。
 使い方は、RUN押したらダイアログ画面が出るので、ファイルを選択すると動画の最初から自動的に変換開始します。こんなもんでいいかなと思ったところでスペースキーを押したら、"soratama.mov"という宙玉レンズ風動画一丁上がりという親切設計です。

 ちなみに7分の動画の変換に丸一日以上かかる激遅ソフトです。多分頑張れば高速化できるのですが、特にやる気はないのでもし高速化できたら教えて下さい。超気が長い人向けソフト☆

import hypermedia.video.*;
import processing.video.*;

PImage tex;
PImage img_blur;
int fps = 30;

OpenCV opencv;
MovieMaker mm;

final float pic_x = 1920;
final float pic_y = 1080;
final float camera_z = 16;
final float sphere_size = 3; // from 0 to camera_z/2
final int backimg_blur_level = 4;
final float soratama_blur_level = 1;
final float backimg_size = 0.0; // from 0 to 0.5
final float soratama_size = 0.6; // from 0 to 1

final float step_ang = 180/3;
final float step_rad = 100;

void setup() {  
  size((int)pic_x, (int)pic_y, P3D);

  println("select movie."); 
  String moviePath = selectInput();

  opencv = new OpenCV( this );
  opencv.movie(moviePath, (int)pic_x, (int)pic_y);

  textureMode(NORMALIZED);

  mm = new MovieMaker(this, (int)pic_x, (int)pic_y, "soratama.mov", fps, MovieMaker.VIDEO, MovieMaker.LOSSLESS); 
  frameRate(fps);
}

PImage rectimage(PImage img){
  
  PImage img_rect;
  if(img.width > img.height){
    img_rect = img.get((img.width-img.height)/2, 0, img.height, img.height);
  }else{
    img_rect = img.get(0, (img.height-img.width)/2, img.width, img.width);
  }
  return img_rect;
}

void draw() {
  opencv.read();
  img_blur = opencv.image();
  img_blur.filter(BLUR, backimg_blur_level);
  
  tex = opencv.image();
  tex = rectimage(tex);
  tex.filter(BLUR, soratama_blur_level);
  
  // Camera Setting
  camera(0, 0, camera_z,
         0, 0, 0,
         0, 1, 0);
  
  // draw blur image background
  float frame_x = pic_x / (camera_z*2);
  float frame_y = pic_y / (camera_z*2);

  noStroke();
  beginShape();
  texture(img_blur);
  vertex(-frame_x, -frame_y, 0, backimg_size, backimg_size);
  vertex(frame_x, -frame_y, 0, 1-backimg_size, backimg_size);
  vertex(frame_x, frame_y, 0, 1-backimg_size, 1-backimg_size);
  vertex(-frame_x, frame_y, 0, backimg_size, 1-backimg_size);
  endShape();  

  // draw soratama
  final float rad_sphere = camera_z/2 - sphere_size;
  final float step_sphere = TWO_PI / step_ang;
  final float step_sphere2 = rad_sphere / step_rad;

  noStroke();
  beginShape();
  texture(tex);
  for(float x = 0; x < rad_sphere; x += step_sphere2){
    for(float ang = 0; ang < TWO_PI; ang += step_sphere){
      vertex(x*cos(ang), x*sin(ang), sqrt(rad_sphere*rad_sphere - x*x),
             soratama_size*(-x*x/(rad_sphere*rad_sphere)*cos(ang))+0.5, soratama_size*(-x*x/(rad_sphere*rad_sphere)*sin(ang)) + 0.5);
    }
  }
  endShape();

  mm.addFrame(); 
}

void keyPressed() {
  if (key == ' ') { 
  mm.finish(); 
  println("save movie."); 
  exit();
  }
}

まとめと今後

 宙玉を増やしたり、高速化したりとか色々改良の余地はあるけど、とりあえず満足したのでこれはこの辺でいったん閉じようかなと。また、色々変な動画作ろうかなと思っています。とりあえず3つくらい案はあるけど、何をいつ頃やるかは未定です。リクエストあれば考慮はします(約束はできないです)のでどしどし下さい、でわでわー☆