読者です 読者をやめる 読者になる 読者になる

顔認識して強制的に人をアヘ顔にするアプリ「アヘ顔男」をリリースしました

電波 動画 Processing

「アヘ顔男」アプリとは

 某機動隊の「笑い男」にインスパイアされて、人をアヘ顔にする「アヘ顔男」というアプリを、何故かとち狂ってつくってしまったのでMac用のフリーソフトとして公開します。素材はインスパイアこそ受けているものの、一応全てオリジナルなのでそんなに問題は無いと思っています。
 ベースは、以前作った「Processingで顔認識を使って強制的にアヘ顔になるソフトを作ってみた」をベースに、某機動隊っぽいアレンジ(回転)を加えてみただけです。
 これでいつでもダブルピースできますね☆

ダウンロードと使い方

 以下のリンク先からダウンロードして下さい。

 そして1280x720のサイズの人の顔が入った動画を用意して下さい。サイズが合わなければiMovieとか適当な動画ソフトでサイズを変えてやって下さい。ピッタリ合わせなくても、比率があっていれば多分問題ないので面倒くさければサイズ変更しなくてもよいです。

 後は、AhegaoManというアヘ顔アイコンをダブルクリックして実行して下さい。フィアルダイアログが出るので、対象の動画を選択するだけです。後はアヘ顔動画が自動で生成されます。スペースボタンを押すと終了します。プログラムと同じフォルダに"ahegao.mov"というアヘ顔化した動画が生成されています。

完成アヘ顔動画

 とりあえず自分の顔で実験してみました。


アヘ顔ダブルピース

カスタマイズ方法

 プログラムと同じフォルダに、以下のような"ahegao.png"と"ahegao_back.png"というファイルがありますが、これの画像を差し替えると好きなアヘ顔を作ることができます。

f:id:karaage:20140208192706p:plain
ahegao.png

f:id:karaage:20140208192715p:plain
ahegao_back.png

 ahegao_back.pngの方は回転するエフェクトがかかりますので注意下さい。基本、Keynoteで作りました。透過pngはMacの標準ソフトの「プレビュー」で作成できますので、"プレビュー 透過png"とかでググって下さい。

参考リンク

C言語による画像回転処理について
回転部分もの凄い参考にしました、というかほぼそのまま

関連記事

Processingで顔認識を使って強制的にアヘ顔になるソフトを作ってみた - karaage. [からあげ]

 ソースコード見たい奇特な方は続きをクリック。WindowsとかLinuxでもProcessingというフリーのプログラミング言語を落として下のソースコードコピペすればアヘ顔ソフト使えるので根気かスキルのある方は、実行だったり改造にチャレンジしてみて下さい。

import hypermedia.video.*;
import java.awt.Rectangle;
import processing.video.*;

boolean rec = true;  // true: recording
int fps = 30;
int w = 1280;
int h = 720;
int angle = 0;

OpenCV opencv;
MovieMaker mm;

PImage img_back;
PImage img_ahegao;
PImage[] img_rotated = new PImage[360];

void setup() {
  size( w, h );

  String moviePath = selectInput();

  opencv = new OpenCV( this );
  opencv.movie( moviePath, width, height );
  opencv.cascade( OpenCV.CASCADE_FRONTALFACE_ALT );

  img_back = loadImage("ahegao_back.png");  
  MakeRotatedImage();

  img_ahegao = loadImage("ahegao.png");
  imageMode(CORNER);

  if(rec){
    mm = new MovieMaker(this, w, h, "ahegao.mov", fps, MovieMaker.VIDEO, MovieMaker.LOSSLESS); 
    frameRate(fps);
  }
}

void MakeRotatedImage(){
  float theta = 0;
  img_back.loadPixels();

  int cx = (int)(img_back.width/2);
  int cy = (int)(img_back.height/2);

  for(int i =0; i<360; i++){
    img_rotated[i] = createImage(img_back.width, img_back.height, ARGB);    
  }

  for(int i =0; i<360; i ++){
    theta = 2*PI*i/360;
    int tmp_sin = (int)(sin(theta)*1024);
    int tmp_cos = (int)(cos(theta)*1024);

    for(int y2 = 0; y2 < img_back.height; y2++){
      for(int x2 = 0; x2 < img_back.width; x2++){
        //          int x1 = (int)((x2-cx)*cos(theta) - (y2-cy)*sin(theta) +cx);
        //          int y1 = (int)((x2-cx)*sin(theta) + (y2-cy)*cos(theta) +cy);
        int x1 = (((x2-cx)*tmp_cos - (y2-cy)*tmp_sin) >> 10) +cx;
        int y1 = (((x2-cx)*tmp_sin + (y2-cy)*tmp_cos) >> 10) +cy;
        if(x1 >=0 && x1 < img_back.width && y1 >= 0 && y1 < img_back.height){
          img_rotated[i].pixels[x2+y2*img_back.width] = img_back.pixels[x1+y1*img_back.width];
        }
      }
    }
  }
}

void draw() {
  opencv.read();
  image( opencv.image(), 0, 0 );
  Rectangle[] faces = opencv.detect();

  for( int i=0; i<faces.length; i++){
    image(img_rotated[angle], faces[i].x-faces[i].width*0.2, faces[i].y-faces[i].height*0.2, faces[i].width*1.4, faces[i].height*1.4);
    image(img_ahegao, faces[i].x+faces[i].width*0.1, faces[i].y+faces[i].height*0.1, faces[i].width*0.8, faces[i].height*0.8);
  }

  if(rec){
    mm.addFrame(); 
  }

  angle +=3;
  if(angle > 359){
    angle =0;
  }
}

void keyPressed() { 
  if (key == ' ') { 
    if(rec){
      mm.finish(); 
    }
  exit();
  }
}