soraなりの日々 - fc2 -

こころにひっかかったもの

[ruby, rails]opencv + rmagick で顔認識アプリ...ソース

えっと前回から。

このエントリーをはてなブックマークに追加
当初は、MOONGIFTさんのココの記事で知った
マルチタッチシステムの touchlib を使って air か ruby
遊ぶつもりだったんだけど、どうやってもサンプルが動かず、
途中で死ぬんよね。。。
(まー、エラソーなこと言ってる割には、ソースすら
 追ってないんダケレド・・・)

で、よくよく見ると touchlib を動かすために入れる
画像認識ライブラリの opencv の方はサクッとサンプルが
動いており、しかも、どのサンプルも面白かった。
なので、こっちで遊ぼう、と。
そんで作ったのが、前回書いた faceanalyze
(何度書いても名前がダセー・・・orz)

で、動いてるソースは?なんだけど、
opencv と imagemagick のインストールが必要ですよ、と。

opencv と imagemagick のインストール自体は、
macports で依存系も含めて全部入れた。
で、mac な人はコレ使うと便利だよ、と。

で、rails アプリの方なんだけど、
rubyopencv と imagemagick を使うために
それぞれのラッパーである objectdetect と rmagick
gem でインストールする。

# gem install rmagick
# gem install objectdetect

あと、画像のアップロードをするので、
これはサクッと rails のプラグインを入れて終らせる、と。

# ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/attachment_fu

これで使うのは全部揃った、と。
あとは実装だけ。
画像のアップデート仕方とかは、今回のメインでは
ないので省略いたします。
ココが詳しいっス。
(と、勝手にリンクして逃げる。すみません。)

ここからメインのソース部分なりまっす。
今回の画像ファイルから opencv で認識させた
顔の部分のみを切り出して、ポラロイド風にする
っていうのは、ミュートス・ラボさんのココの記事を
大変参考にさせていただきました。
(というか、ruby 部分の考え方はマンマ・・・)

んで、それを元に作成した今回のメインのクラス。

require 'RMagick'
require 'objectdetect'

class PhotoDetector
  @@CASCADE_FPATH = "/your/path/opencv/haarcascades/haarcascade_frontalface_alt2.xml"

  def initialize(output_path, cascade=@@CASCADE_FPATH)
    @output_path = output_path
    @cascade = cascade
  end

  def create(id, title, fname, image_data, content_type="")

    if !File.exist?(@output_path + id.to_s) or !FileTest::directory?(@output_path + id.to_s) then
      Dir::mkdir(@output_path + id.to_s)
    end
    ext = File::extname(fname)
    image = Magick::Image.from_blob(image_data).shift
    #image.format = content_type
    path = @output_path + id.to_s + "/"
    file = path + title + ext
    image.write(file)

    images = Magick::ImageList.new()
    base = Magick::ImageList.new(file)
    detectors = ObjectDetect::detect(@cascade, file)
    detectors.each do |pos|
      x, y, w, h = pos
      detect = base.crop(x, y, w, h)
      images << detect
    end
    return if images.nil? or images.size <= 0

    i = 1
    images.each do |image|
      file = path + title + "-#{i}" + ext
      image.write(file)
      i += 1
    end

  end

  def polaroid(id, images)
    images.each do |key, value|
      clown = Magick::Image.read(@output_path + id.to_s + "/" + key).first
      cols, rows = clown.columns, clown.rows
      clown[:caption] = value
      clown = clown.polaroid { self.gravity = Magick::CenterGravity }
      clown.change_geometry!("#{cols}x#{rows}") do |ncols, nrows, img|
        img.resize!(ncols, nrows)
      end
      fname = File::basename(key, '.*')
      clown.write(@output_path + id.to_s + "/" + fname + ".png")
    end
  end
end

PhotoDetector::create() メソッドで元画像から
objectdetect 経由でobjectcv に顔を認識させて、
顔のみの画像を作成していきます。

PhotoDetector::polaroid() メソッドで、今度は、
PhotoDetector::create() メソッドで作成された
顔の画像をそれぞれポラロイド風にして保存していきます。

で、使用してるところ。

PhotoDetector::create() :
photo = @analyze_photo.photo
detector = PhotoDetector.new(UPLOAD_FPATH)
detector.create(params[:id], @analyze_photo.title, photo.filename, photo.current_data, photo.content_type)

PhotoDetector::new() で顔のみの画像を
作成する場所を指定します。
@analyze_photo.photo には、
アップロードした画像ファイルが入っています。

PhotoDetector::polaroid():
detector.polaroid(params[:id], images)

images には、
{顔のみで作成した画像ファイル名, 一言メッセージ}
のハッシュを作成しておきます。

いじょ。


今回 opencv を使って作成したこの faceanalyze なんですが、
opencv 自体が他依存が多く、しかも、imagemagick 含め
コンパイルが必須なものなので、それらを許さない普通の
レンタルサーバでは使えないってことがなんとも悲しいっす。。。

なので、このアプリも日の目を見る事はないんだろな・・・orz



このエントリーをはてなブックマークに追加

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバックURLはこちら
http://sora2hs.blog70.fc2.com/tb.php/414-befee51d
この記事にトラックバックする(FC2ブログユーザー)