#はじめに
こんばんは.
このエントリーは プロ生ちゃん Advent Calendar 2014 の第25日目の記事です.
#環境
- Mac OSX 10.10.1 Yosemite
- Ruby 2.0.0p481
#目的
- Rubyで顔認識したい
- ruby-opencvなるものがあるらしい
- ruby-opencvで自分の顔をプロ生ちゃんにしよう!
- gifアニメーションも作りたい!
#使うもの
#環境構築
- ruby-opencvの導入
$ brew tap homebrew/science
$ brew install opencv
$ gem install ruby-opencv -- --with-opencv-dir=/path/to/opencvdir
今回は使いませんがruby-opencvをcloneして遊ぶと勉強になります
- ImageMagickの導入
以下のリンク先のパッケージインストーラーを用いてインストール
ImageMagick installer for Mac OS X
#実装
今回,顔の検出にはOpenCV付属の顔検出用分類器を使います.
同じ手順でインストールしていれば以下のコマンドで大丈夫です.
$ cp /usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml ./haarcascade_frontalface_alt.xml
僕のソースコードをそのまま使ってみる人は
$ mkdir gif
ruby-opencvのサンプル,face_detect.rbを参考に開発していきます.
これをそのまま動かすだけで顔を検出して赤い線で囲みます!すごい!
当初の顔検出したい願望が叶ってしまった!
##やりたいこと① 自分の顔とプロ生ちゃんの顔を置き換えたい
検出した顔の領域とプロ生ちゃん アイコンジェネレーターで作ったアイコンを置き換えてみましょう!
detector.detect_objects(image).each do |rect|
#imageを顔検出した範囲に限定
image.set_roi rect
#プロ生ちゃん画像を顔検出したサイズにリサイズ
resize_pronamachan = pronama.resize rect
#顔検出した範囲とプロ生ちゃんの画像を1画素ずつ置き換える
(image.rows * image.cols).times do |j|
image[j] = resize_pronamachan[j]
end
#範囲の限定の開放
image.reset_roi
end
##やりたいこと② アイコンの背景を透過させたい
今回,プロ生ちゃん アイコンジェネレーターで簡単に背景の色を変えられるので,背景を使われてなさそうな色(今回はRGB(f0,f0,f0))にしてその色の時は置き換えないという手法で透過.
(image.rows * image.cols).times do |j|
#rectの範囲でrgb(f0,f0,f0)以外の時置き換え(背景透過)
image[j] = resize_pronamachan[j] if resize_pronamachan[j][0] != 240.0 && resize_pronamachan[j][0] != 240.0 && resize_pronamachan[j][0] != 240.0
end
##やりたいこと③ gifアニメーションをつくりたい
生成された画像を000〜999の数字を振って保存.
(読みながら実装している人は保存しすぎに注意)
#生成された画像の保存
image.save_image("./gif/image%03d.jpg"%i.to_s)
その後,ImageMagickの以下のコマンドで変換して保存
$ convert ./gif/*.jpg ./gif/hoge.gif
結果は最後に!
#まとめると
#!/usr/bin/env ruby
# face_detect.rb
require "rubygems"
require 'opencv'
include OpenCV
window = GUI::Window.new "face detect"
#カメラからの読み込み
capture = CvCapture.open
#顔検出用分類器の読み込み
detector = CvHaarClassifierCascade::load "./haarcascade_frontalface_alt.xml"
#取り込む画像の選択(プロ生ちゃん!)
puts "どのプロ生ちゃんにしますか?"
puts "1:ノーマル"
puts "2:サンタ"
puts "3:アニメーション"
select_pronamachan = gets.to_i
if select_pronamachan == 1 then
pronama = IplImage.load './pronama.png'
elsif select_pronamachan == 2 then
pronama = IplImage.load './pronamasanta.png'
elsif select_pronamachan == 3 then
pronama=Array.new(5) { |i| }
pronama[0] = IplImage.load './pronama1.png'
pronama[1] = IplImage.load './pronama2.png'
pronama[2] = IplImage.load './pronama3.png'
pronama[3] = IplImage.load './pronama4.png'
pronama[4] = IplImage.load './pronama5.png'
end
puts "フレーム数は?(200まで)"
gets.to_i.times do |i|
image = capture.query
image = image.resize CvSize.new 480, 270
random = 0
if i % 5 == 0 then
random = rand(5).to_i
end
#顔検出
detector.detect_objects(image).each do |rect|
#imageを顔検出した範囲に限定
image.set_roi rect
#プロ生ちゃん画像を顔検出したサイズにリサイズ
unless select_pronamachan ==3 then
resize_pronamachan = pronama.resize rect
else
resize_pronamachan = pronama[random].resize rect
end
#顔検出された範囲でRGB(f0,f0,f0)以外の時置き換え
(image.rows * image.cols).times do |j|
image[j] = resize_pronamachan[j] if resize_pronamachan[j][0] != 240.0 && resize_pronamachan[j][1] != 240.0 && resize_pronamachan[j][2] != 240.0
end
#範囲の限定の開放
image.reset_roi
end
#生成された画像の表示
window.show image
#生成された画像の保存
image.save_image("./gif/image%03d.jpg"%i.to_s)
break if GUI::wait_key(100)
#200回で終了
break if i == 199
end
$ convert ./gif/*.jpg ./gif/hoge.gif
こんなgifが作れました!
(アップロード制限回避のためにリサイズと減色してます)
#まとめ
今回,ruby-opencvを軽く触ってみてプロ生ちゃんを使って遊びましたがruby-opencv,opencvは他にも色々なことが出来そうです.
興味が湧いた人はOpenCVをもっと使いこなして『俺がプロ生ちゃんだ!』しましょう!!