前回「Processingで顔認識を使って強制的にアヘ顔になるソフトを作ってみた」でProcessingで色々動画を弄ってみたわけですけど、写真の処理とかにも普通に使えるんじゃ無いかなとふと思い作ってみました。
ちなみに前回はあれだけ身体を張ったのにもかかわらず、全くといっていいほど反響ありませんでした。多分みんなドン引きしたのでしょう。よって今回でこのシリーズは最終回にしようと思います、みなさん短い間でしたがご清聴ありがとうございました。
アヘ顔画像生成ソフト
それでは早速アヘ顔になるソフトのコードです。Processing、Open CVのインストールといった準備は前回の記事を参照して下さい。あとは下のコードをコピペして、同じフォルダにアヘ顔にしたい写真を「source.jpg」という名前で保存して実行すればOKです。
import hypermedia.video.*; import java.awt.Rectangle; int w = 1024; int h = 768; OpenCV opencv; PImage source_img; PImage ahegao_img; void setup() { size( w, h ); opencv = new OpenCV( this ); opencv.loadImage("source.JPG", width, height); opencv.cascade( OpenCV.CASCADE_FRONTALFACE_ALT ); ahegao_img = loadImage("ahegao.png"); imageMode(CORNER); } void draw() { opencv.read(); image( opencv.image() , 0, 0 ); Rectangle[] faces = opencv.detect(); for( int i=0; i<faces.length; i++){ image(ahegao_img, faces[i].x, faces[i].y, faces[i].width, faces[i].height ); } } void keyPressed() { if(key == 'p' || key == 'P') { // save image save("screenshot.png"); println("screen saved."); } exit(); }
int w = 1024; int h = 768; は写真の解像度に合わせて設定して下さい。あんまり大きいとオーバーフロ起こすので、その場合は2とか3で割った数を入力してやればよいです。
実行してうまい具合にアヘ顔になったら「p」を押して下さい「screenshot.png」というアヘ顔ファイルを吐き出してくれます。
実施例
実行例をいくつか公開します。
まあこんな感じにアヘ顔になります。 うまく顔認識しないときは、Rectangle faces = opencv.detect();の行のdetect関数に適当なパラメータを引数でわたしてやると認識してくれるときがあります。例えば、 Rectangle faces = opencv.detect(1.2, 0, 1, 10, 10); みたいな感じで。顔が大きいときは、1番目と4番目と5番目の引数を大きくしてやるとよいです。1番目の引数は1.1〜2くらいまでの間で設定するのがよさそうです。あんまり小さくすると時間がかかるのと誤認識多くなってきます。詳しくはリファレンスを調べてみて下さい。ちなみに僕はよく理解できませんでした(ダメダメ)。
モザイクフォト生成ソフト
もひとつおまけに、フォトモザイク(モザイク状に並べた写真で写真を表現するやつ)もできそうだったのでやってみました。というかほとんどコピペです。まずはソースコード。
import hypermedia.video.*; import java.awt.Rectangle; PImage img; int mosaicWidth = 20; int mosaicHeight = 10; int w = 1024; int h = 768; void setup() { size(w, h); noStroke(); background(0); img = loadImage("source.JPG"); image(img, 0, 0); loadPixels(); } void draw() { println("h="+height); println("w="+width); for(int j = 0; j < height; j+=mosaicHeight) { for(int i = 0; i < width; i+=mosaicWidth) { color c = pixels[j * width + i]; tint(red(c), green(c), blue(c)); image(img, i, j, mosaicWidth, mosaicHeight); } } println("finished!!"); } void keyPressed() { if(key == 'p' || key == 'P') { // save image save("screenshot.png"); println("screen saved."); } exit(); }
あんまり細かい写真だと面白くないので、シンプルなものがよいです。int mosaicWidth = 20;
int mosaicHeight = 10;はまずは大きめの値から徐々に小さくしていくのがよいかなと思います。設定値によってはモザイク状の絵が出てくるまで結構な時間がかかります。
参考
『Processingで画像データを扱う』
フォトモザイクのプログラムはほとんどここのコピペです
『絵心がなくても簡単に絵が描ける Processing』
わかりやすい連載。スクリーンショットの保存の仕方とかはこれを参考にしました
『OpenCV detect()関数のリファレンス』
よく読んでdetect関数の引数弄れば、顔認識精度を上げる事ができるかもしれません、僕は理解がイマイチでした。