opencvr-0.3リリース
こちらの記事の続き。
相変わらずgemになっていないので使う人はいない気がしますが、0.3をリリースしました。
対応する引数・戻り値型の追加
以下の型に対応しました。
-
char
,uchar
,vector_char
,vector_uchar
- `std::vector<String>
const char*
クラスインスタンスを返す関数の対応
関数の戻り値としてサポートするクラスは、これまではcv::Mat
やcv::Scalar
など特別に対応したクラスのみでしたが、0.3からはその他のクラスにも対応しました。
CV_WRAP_ASの対応
C++のヘッダでCV_WRAP_AS
が指定されているものはC++のメソッド名とは異なる名前でバインドされます。主にoverloadされている関数で、Pythonでは同名にできないものに対して使われます。Rubyでも別名でバインドするようにしました。
Enum型
enum型引数・戻り値を持つ関数に対応しました。なお、cv::imread()
は引数flags
にcv::ImreadModes
を取りますが、引数型はint
なので以前から対応しています。
コンストラクタがないクラス
opencvrではC++のクラスのコンストラクタに対してRubyのinitialize
相当のメソッドをバインドさせています。そのためコンストラクタがないクラスはインスタンス化することができません。
ただし、コンストラクタがないクラスの多くは抽象クラスで、コンストラクタではなく別の方法でインスタンスを取得します(例えばインスタンスを生成するスタティックメソッドなど)。このようなクラスについてはすでに対応していました。
コンストラクタがなく、かつ抽象クラスでもないクラスは対応できていませんでしたが、0.3で対応しました。具体例としてはcv::Stitcher
があります。
新規対応クラスの例
cv::Stitcher
0.3から対応したクラスの一つにcv::Stitcher
があります。これは複数の画像を繋げて大きな画像を作るものです。例えば以下の写真は大室山という山の上から撮ったものです。
これらの画像が./images/
以下にある場合、パノラマ画像を作るには以下のようにします。
#!/usr/bin/env ruby
$:.unshift(__dir__)
require 'numo/narray'
require 'cv2'
src_paths = Dir.glob("./images/*.JPG")
imgs = []
src_paths.each{|path|
img = CV2::imread(path)
imgs << img
}
stitcher = CV2::Stitcher::create()
ret, pano = stitcher.stitch(imgs)
CV2::imwrite("pano.jpg", pano)
出来上がった画像はこんな感じ。
長方形を切り出すと以下のようになります。
cv::VideoWriter
cv::VideoWriter
も使えるようになりました。以下は動画のサイズを縦横半分にするスクリプトです。
#!/usr/bin/env ruby
$:.unshift(__dir__)
require 'numo/narray'
require 'cv2'
in_path = "./in.mp4"
vid = CV2::VideoCapture.new(in_path)
orig_width = vid.get(CV2::CAP_PROP_FRAME_WIDTH).to_i
orig_height = vid.get(CV2::CAP_PROP_FRAME_HEIGHT).to_i
fps = vid.get(CV2::CAP_PROP_FPS).to_i
fcount = vid.get(CV2::CAP_PROP_FRAME_COUNT).to_i
puts "#{orig_width}x#{orig_height} #{fps} #{fcount}"
out_path = "./out.mp4"
width = (orig_width/2).to_i
height = (orig_height/2).to_i
# Pythonならcv2.VideoWriter_fourcc("m", "p", "4", "v")と書けるが
# Rubyでは今のところ文字コードを直接指定する
fourcc = CV2::VideoWriter::fourcc(0x6d, 0x70, 0x34, 0x76)
writer = CV2::VideoWriter.new(out_path, fourcc, fps, [width, height])
n = 0
loop do
ret, frame = vid.read()
break if !ret
resized = CV2::resize(frame, dsize=[width, height])
writer.write(resized)
n += 1
print "\r#{n}/#{fcount}"
end
puts
writer.release()
vid.release()
今後やりたいこと
gem対応
そろそろgemを作りたいところですが、opencvrのようにネイティブのバイナリを含むものはバイナリ部分をどうするかという問題があります。この問題については以下の記事が詳しいです。
Pythonではpip install
でバイナリまでインストールされますが、Rubyではどうするか迷ってます。
リファクタリング
gen2rb.pyは非常に汚いコードになっているので(多分自分史上最恐)、そろそろこれをリファクタリングしないと機能追加できなそうです。
Discussion