ruby-opencvでのROIの操作

OpenCVには「ROI」(Region Of Interest:注目領域)という概念があり、画像に対してこれを設定すると、その領域に対してのみ種々の操作が行なわれる様になる。

ROIを設定している状態で画像を描画させるとROIの部分のみ描画されるし、copyを行なうとROIの部分のみコピーされる。

require 'opencv'
include OpenCV
win = GUI::Window.new("w")
img1 = IplImage.load(ARGV.shift) # 1032x581の画像を読み込む。 #
img1.set_roi(CvRect.new(320,100, 300,200)) # 幅300x縦200の矩形領域をROIとしてセット(オフセット位置=(320,100))
img2 = img1.copy
img1.reset_roi;img2.reset_roi # ROIを解除するには reset_roi 
printf("img1 : %dx%d\n", img1.width, img1.height) #⇒ 1032x581
printf("img2 : %dx%d\n", img2.width, img2.height) #⇒ 300x200
win.show img1
GUI::wait_key 0
win.show img2
GUI::wait_key 0

irbからOpenCVを叩く

irbを使うとObject.methodsでメソッド一覧も確認できるし、フィルタの効果の確認とかもすぐできるし便利。

irb(main):001:0> require 'opencv';include OpenCV
=> Object
irb(main):002:0> img=CvMat.load("Tulip.jpg")
=> #<OpenCV::CvMat:0x7d2080>
irb(main):003:0> w=GUI::Window.new("w")
=> #<OpenCV::GUI::Window:0x7cb794>
irb(main):004:0> w.show img.BGR2GRAY.canny(100,100)
=> #<OpenCV::GUI::Window:0x7cb794>
irb(main):005:0> GUI::wait_key(99)
=> nil
irb(main):006:0> w.methods
=> [:alive?, :destroy, :resize, :move, :show_image, :show, :set_trackbar, :set_m
ouse_callback, :on_mouse, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :si
ngleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :un
trusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_metho
ds, :protected_methods, :private_methods, :public_methods, :instance_variables,
:instance_variable_get, :instance_variable_set, :instance_variable_defined?, :re
move_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_s
end, :respond_to?, :extend, :display, :method, :public_method, :singleton_method
, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :
!=, :instance_eval, :instance_exec, :__send__, :__id__]

でも、上記で「w.show img」としても、即座にウィンドウ上にimg(画像)は表示されない。
GUI::wait_key(99)とかをコールしてやると初めて表示される。
(VS10版opencv2.4.11/mswin版ruby2.2で確認。他の環境でも同様かは未確認)

ruby-opencvでキャプチャ動画を保存

引数指定したデバイスorファイルを動画保存する。

require 'opencv'
include OpenCV
captureDevice = 0
if ARGV.size > 0
  captureDevice = ARGV.shift
  captureDevice = captureDevice.to_i if /^\d$/ =~ captureDevice
end
win = GUI::Window.new("win")
cap = CvCapture.open(captureDevice)
begin
  fps = cap.fps
  if fps > 67 or fps < 5 # 変なfpsの時は10fps(100msec間隔)にする
    fps = 10
  end
rescue
  fps = 10
end
frame_msec = 1000/fps
out = CvVideoWriter.new("out.avi", 'XVID', fps, CvSize.new(cap.width, cap.height))
loop do
  img = cap.query
  break unless img
  win.show img
  out.write(img)
  c = GUI::wait_key(frame_msec)
  break if c == 27
end
out.close

指定されたファイルをオープン、
動画再生しつつ、"out.avi"として保存する。

C言語だと cvCreateVideoWriter() とか cvSize() とかをコールするんだが、
ruby-opencvだと CvXxx.new()である。

今手元にUSBカメラとかのキャプチャデバイスが無いので、上記でちゃんと動くかどうかは未確認。
(mp4を読み込んで、avi保存できることだけ確認した)

ruby-opencvでtrackbarを使って色々なパラメータを試す

Cで書くよりrubyで書いた方が、トラックバーも簡単に使える。

require 'opencv'
include OpenCV

inp_win = GUI::Window.new('Input')
out_win = GUI::Window.new('Output')

filename = ARGV.shift
inp_img = CvMat.load(filename)

inp_win.show inp_img
out_win.set_trackbar("TraBar",1000,150) do |v|
  out_win.show inp_img.BGR2GRAY.canny(120,v)
end
out_win.show inp_img.BGR2GRAY.canny(120,150)

GUI::wait_key

Cで上記コードを書こうとしたら、わざわざコールバック用の関数を定義して、それをトラックバーにバインドして、トラックバー自体をウィンドウにバインドして…
とかしなければいけないんだけど、ruby-opencvなら、win.set_trackbar(){block;}だけでOK。

トラックバーを左右に動かす度に動かした後の値でblockがコールされて、表示されてる絵が更新される。

ruby-opencvでカメラキャプチャして画像加工

require 'opencv'
include OpenCV
win = GUI::Window.new("win")
cap = CvCapture.open(0)
mode = nil
loop do
  out = img = cap.query
  next unless img
  case mode
  when 'c'; out = img.BGR2GRAY.canny(120,200)
  end
  win.show out
  key = GUI::wait_key(100)
  if key
    mode = key.chr
    break if mode == 'q'
  end
end

CvCapture.open()は、文字列で引数指定すると動画ファイルをオープン、
数字指定でPCに接続されているN番目のキャプチャデバイスをオープンする。

なので、上記の様に CvCapture.open(0) すると、最初に見つかったキャプチャデバイス(例えば USB接続されている Webカメラ)から動画取込できる状態になる。

上記では、'c'を押されたら、取り込んだ画像をモノクロ変換して(RGBをGRAYスケールに変換)、canny法でエッジ抽出するフィルタをかけて表示する様にしている。

ruby-opencvで動画ファイル再生

『Class: OpenCV::CvCapture ― Documentation for ruby-opencv (0.0.14)』
http://www.rubydoc.info/gems/ruby-opencv/OpenCV/CvCapture

require 'opencv'
include OpenCV
vid = CvCapture.open(ARGV.shift)
win = GUI::Window.new('win')
printf("%d x %d, %d fps, %d frames \n", vid.width, vid.height, vid.fps, vid.frame_count)
frame_msec = 1000/vid.fps
loop do
  img = vid.query
  break unless img
  win.show img
  c = GUI::wait_key(frame_msec)
  break if c == 27
end

こんな簡単なスクリプトで、引数指定したMPEGとかの動画ファイルを再生可能。

ruby-opencvのサンプルソースとか

ruby-opencvの残念なのは、ドキュメントとか情報が少ないところ。
でも、標準添付の examples だけでも実は結構情報がある。一通り眺めるだけで、かなり色々できる。
irbから動かして、どんなメソッドがあるか調べることもできるし…で、ドキュメントを充実させようと考える人が少ないのかもしれない。

実際、OpenCV公式や、以下のサイトを眺めて、大体のあたりを付けて、exaples のソースをコピペして動かしたり、irbから叩いてカット&トライしたりして、大抵のことはできるんじゃないかと思う。

OpenCV 2.1の関数 CとC++の対照表 (未完) - schima.hatenablog.com』
http://schima.hatenablog.com/entry/20100814/1281795242

『File: README — Documentation for ruby-opencv (0.0.14)』
http://www.rubydoc.info/gems/ruby-opencv/frames

以下、「c:/Ruby/lib/ruby/gems/2.2.0/gems/ruby-opencv-0.0.14/examples」で grep '^#' して、適当に編集してみた。

alpha_blend.rb:# Alpha blending sample with GUI
convexhull.rb:# Draw contours and convexity defect points to captured image
face_detect.rb:# face_detect.rb
find_obj.rb:# A Demo Ruby/OpenCV Implementation of SURF
find_obj.rb:# See https://code.ros.org/trac/opencv/browser/tags/2.3.1/opencv/samples/c/find_obj.cpp
houghcircle.rb:# houghcircle.rb
inpaint.rb:# inpaint.rb
match_kdtree.rb:# A sample of matching SURF feature points using kd-tree
match_kdtree.rb:# See http://tech.groups.yahoo.com/group/OpenCV/message/62318
match_template.rb:# A demo of Ruby/OpenCV's match_template function
paint.rb:# paint.rb
snake.rb:# snake.rb
contours/bounding-box-detect-canny.rb:# Detects contours in an image and
contours/bounding-box-detect-canny.rb:# their boundingboxes
contours/contour_retrieval_modes.rb:# This file shows the different retrieval modes for contour detection
facerec/create_csv.rb:# This is a tiny script to help you creating a CSV file from a face
facerec/create_csv.rb:# database with a similar hierarchie:
facerec/create_csv.rb:# See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
facerec/facerec_eigenfaces.rb:# Eigenfaces sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_eigenfaces.cpp
facerec/facerec_eigenfaces.rb:# See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
facerec/facerec_fisherfaces.rb:# Fisherfaces sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_fisherfaces.cpp
facerec/facerec_fisherfaces.rb:# See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html
facerec/facerec_lbph.rb:# LBPH sample in ruby-opencv, equivalent to http://docs.opencv.org/trunk/_downloads/facerec_lbph.cpp
facerec/facerec_lbph.rb:# See http://docs.opencv.org/trunk/modules/contrib/doc/facerec/facerec_tutorial.html