第3回 Ruby/OpenCV進捗報告

はじめに

連休もそろそろ終わりですが、皆様いかがお過ごしでしょうか?
Ruby/OpenCVの開発はゆるゆる進んでおります。

進捗

gemが作れるようになりました!(主にpctingさんのおかげ)

pctingさんがナイスな修正をしてくれたおかげで、Ruby/OpenCVのgemがRakeで簡単に作れるようになりました。

gemを作ってインストールするには、

$ git clone git://github.com/ser1zw/ruby-opencv.git
$ cd ruby-opencv
$ bundle install
$ rake gem
$ gem install pkg/opencv-*.gem

という感じでOKです*1

$ rake install_gem

とやっても大丈夫なはずなのですが、RVMを使っているとうまくいかないことがある(パスの問題かも)ので、要調査…。

ffcall無しでもGUIが使えるようになりました!(ただしTrackbar以外)

これまではffcallがインストールされていない場合、WindowなどGUIに関する機能が使えませんでした。しかし、実際にffcallに依存しているのはWindow#set_trackbarのみ*2ですので、その他の機能についてはffcall無しでも使用できるように変更しています。

現状ではffcallまわりがちょっと不安定な上、他のプラットフォームで動かすときに困りそうなので、できれば使わないようにしたいと思っています。要はクロージャっぽいものが使えればいいので、Boost使ってなんとかならないかなーとか、でもこれだけのためにBoost持ち出すのもなーとか、そもそもC++書けないしなーとか考えつつ、代替案を検討中です。

テスト

ユニットテストの進捗は以下の通りです。GUIまわりの修正とテストがだいたい完了しており、CvMatも地味に進んでいます。
まだ手をつけてないものも結構あるのですが、さっさと終わらせて新機能の追加に移りたいところです。

クラス/モジュール 進捗
CvMat 90%完了
OpenCV cvCvtColor系の機能がけっこう残ってる
CvSeq だいたい完了
CvRect だいたい完了
CvContour だいたい完了
CvMoments だいたい完了
CvPoint3d32f だいたい完了
CvScalar だいたい完了
CvPoint だいたい完了
CvSize2d32f だいたい完了
CvPoint2d32f だいたい完了
CvSize だいたい完了
CvChain だいたい完了
CvCircle32f だいたい完了
CvBox2d だいたい完了
CvConnectedComp だいたい完了
CvLine だいたい完了
CvTwoPoints だいたい完了
CvTermCriteria だいたい完了
IplImage だいたい完了
CvHumoments だいたい完了
CvFont だいたい完了
IplConvKernel だいたい完了
GUI だいたい完了
MouseEvent だいたい完了
TrackBar だいたい完了
Window だいたい完了
Curve まだやってない
CvAvgComp まだやってない
CvCapture まだやってない
CvChainCode まだやってない
CvCondensation まだやってない
CvContourTree まだやってない
CvConvexityDefect まだやってない
CvError まだやってない
CvHaarClassifierCascade まだやってない
CvHistogram まだやってない
CvMatND まだやってない
CvMemStorage まだやってない
CvSet まだやってない
CvSlice まだやってない
CvSparseMat まだやってない
CvVideoWriter まだやってない
Point3dSet まだやってない
PointSet まだやってない

デモ

前回までとはちょっと趣向を変えて、OpenCVのGUIを使ったペイントのデモです*3
マウスのドラッグで線の描画、右クリックで塗りつぶし、ESCキーで終了です。また、キーを入力して線の太さの変更、色名を入力して線の色の変更ができます。
環境はRuby 1.9.2+OpenCV 2.2+Ubuntu 11.04です。

require 'opencv'
include OpenCV

# Windowに描画領域を作成
window = GUI::Window.new('free canvas')
canvas = CvMat.new(500, 500, CV_8U, 3).fill!(CvColor::White)
window.show canvas

colors = CvColor::constants.collect{ |i| i.to_s }

usage =<<USAGE
[mouse]
drag            - draw
right button    - fill by color
[keyborad]
1 to 9          - change thickness of line
type color name - change color
esc             - exit
USAGE
puts usage

# 線の色と太さ
opt = {
  :color => CvColor::Black,
  :tickness => 1
}

# マウスイベントの処理
point = nil
window.on_mouse{ |m|
  case m.event
  when :left_button_down # マウスドラッグで線の描画
    canvas.line!(m, m, opt)
    point = m
  when :move
    if m.left_button?
      canvas.line!(point, m, opt) if point
      point = m
    end
  when :left_button_up
    point = nil
  when :right_button_down # マウスの右ボタンで塗りつぶし
    canvas.flood_fill!(m, opt[:color])
  end
  window.show canvas
}

# キー入力の処理
color_name = ''
while key = GUI.wait_key
  next if key < 0 or key > 255
  case key.chr
  when "\e" # ESCキーで終了
    exit
  when '1'..'9' # 線の太さを変更
    puts "change thickness to #{key.chr.to_i}."
    opt[:thickness] = key.chr.to_i
  when /[A-Za-z]/ # 線の色を変更
    color_name << key.chr
    choice = colors.find_all{ |i| i =~ /\A#{color_name}/i }
    if choice.size == 1
      color = choice[0]
      puts "change color to #{color}."
      opt[:color] = CvColor::const_get(color)
    end
    color_name = '' if choice.size < 2
  end
end


こんな感じでペイントっぽいことができます。
f:id:ser1zw:20110507081608p:image

まとめ

そんなわけで、第3回Ruby/OpenCV進捗報告でした。

リポジトリはこちら

人柱はいつでも大歓迎ですよー。
ser1zw/ruby-opencv - GitHub
https://github.com/ser1zw/ruby-opencv

*1:bundlerが入っていない人は、事前に gem install -r bundler してください

*2:もともとはWindow#set_mouseeventでもffcallの機能を使用していたのですが、使わないように修正しました

*3:もともとサンプルとして添付していたのですが、今までまともに動かなかったという…