名前
Cv - 何かコンピュータビジョンでやってみるとき、あなたの助けになるように (只今、書き直し中)
概要
use Cv;
my $image = Cv->LoadImage("/path/to/image");
$image->ShowImage("image");
Cv->WaitKey;
my $capture = Cv->CaptureFromCAM(0);
while (my $frame = $capture->QueryFrame) {
$frame->Flip(\0, 1)->ShowImage;
my $c = Cv->WaitKey(100);
last if $c >= 0;
}
説明
Cv
は OpenCV コンピュータビジョンライブラリの Perl インタフェースで す。OpenCV の C言語のリファレンスを元にしたので、リファレンスとして http://opencv.willowgarage.com/ が使えます。とは言え、異なる部分もあり、 少しずつ文書にまとめています。
中途半端で申し訳ありません。
コンピュータビジョンは少し難しいので、Perl のスローガンに則り「簡単なこ とは簡単に、難しいこともそれなりに」を心掛けています。
オブジェクト
オブジェクトの作成と解放
OpenCV の画像やマトリクスのオブジェクトは、C言語と同様に Createなんとか()
で作ります。
my $img = Cv->CreateImage([ 320, 240 ], IPL_DEPTH_8U, 3);
my $mat = Cv->CreateMat(240, 320, CV_8UC4);
オブジェクトは new
で作ることもできます。画像を作る CreateImage() と マトリクスを作る CreateMat() は、上の例のとおり呼び出し形式が違いますが。 new
なら同じように作ることができます。
my $arr = Cv::Image->new($size, $type);
my $arr = Cv::Mat->new($size, $type);
my $arr = Cv::MatND->new($size, $type);
my $arr = Cv::SparseMat->new($size, $type);
またオブジェクトを作るとき、元のオブジェクトがあれば引数を省略すること もできます。
my $sameone = $img->new;
my $gray = $color->new(CV_8UC1);
オブジェクトが不要になったら、C言語では Createなんとか()
と対の Releaseなんとか()
で利用者がオブジェクトを解放します。Perl は同じ場 面で DESTROY
を呼ぶので、Cv
はこの仕組みを使ってオブジェクトを解 放します。従って解放について利用者が注意を払う必要はありません。解放で きないオブジェクトは Cv::なんとか::Ghost
というクラスで bless し、 Cv
の中で識別できるようにしています。
OpenCVのデータ型とCvのクラス名
OpenCV には画像やマトリクスのデータ型として CvImage
, CvMat
, CvMatND
, CvSparseMat
など、いろいろな型があります。Cv
は、この データ型とクラス名が対応しています。クラス名は、Cv
の後に :: を置い た名前で、たとえば、CvImage
は Cv::Image
に、CvMat
は Cv::Mat
に対応しています。そして、オブジェクトは、OpenCV のデータの ポインタをそのデータ型に対応するクラス名で bless したものになります。
OpenCV の画像やマトリクスのデータ型 CvMat
、CvImage
は、CvArr
から導出されたデータ型です。従って、画像やマトリクスは CvArr
を介し て受け渡されます。Cv
でも同様に、スーパクラスとして Cv::Arr
を用 意し、メソッドはできるだけここに置くことにしました。
OpenCV には更にシーケンスと呼ばれる動的なデータ型もありますが、これにつ いては、Cv::Seq を参照してください。
データ領域の共有
OpenCV の画像やマトリクスは、ヘッダ部とデータ部が分れており、データ部の ないヘッダだけのオブジェクトが作れます。データのないことを伝えるために、 次のとおり undef を渡します。
my $arr = Cv::Mat->new([$rows, $cols], $type, undef);
このようにして作成したヘッダだけのオブジェクトは、GetRows(), GetCols() のようにデータ部を共有するメソッドで使っています。
(注意) コードを見ると、undef の代りに文字列でデータ部を与えることが可能 だと気付くかもしれません。別のシステムで作成した画像やマトリクスを扱う とき、データ変換の手間を減らすことができると考える人もいると思います。 しかし、オブジェクトが開放されるとき Cv::Image ではエラーが起きます。 Cv::Mat はなんとなく動いているように見えますが、安定していません。文字 列でデータ部を渡さないようにしてください。(これは bugs へ)
OpenCVの構造体
Cv のオブジェクトは、OpenCV の構造体をその型名に対応するクラス名で bless したものです。従って、Cv (Perl) から OpenCV の構造体は直接操作で きません。しかし、OpenCV に同梱されているサンプルでは、構造体の大きさや 要素の型を直接使っています。たぶんそれが簡単なんでしょう。Cv でも同様の 使い方をするために、構造体のメンバの名前でメソッドを作りました。詳細は "Cvで追加されたメソッド" を参照してください。
メソッド
メソッドの名前とその統合
メソッドの名前は、OpenCV の関数名の頭の cv
を省いた名前と、名前のは じめの大文字を小文字に直したものが使えます。次の 2つの例はどちらも cvCreateMat()
を呼び出します。
my $mat = Cv->CreateMat(240, 320, CV_8UC3);
my $mat = Cv->createMat(240, 320, CV_8UC3);
それから cvAdd()
と cvAddS()
のような類似した関数はより簡潔な名前、 つまりこの例では Add()
にまとめました。おそらく C言語では異なる型の 引数を受けとることができないので、分けるしかなかったのでしょう。Cv
ではこれらを統合し、引数で呼び出す関数を決めています。
my $ar2 = Cv->CreateImage(); # ref Cv::Image
my $sc2 = cvScalar(); # ref ARRAY
my $d = $ar->Add($ar2); # cvAdd($ar, $ar2)
my $d = $ar->Add($sc2); # cvAddS($ar, $sc2)
統合した関数は次のとおり。あまり多くありません。リファレンスを参照して、 cvなんとか()
と cvなんとかS()
の両方あるものがそうだと考えてください。
AbsDiff(), Add(), And(), Cmp(), InRange(), Max(), Min(), Or(), Sub(), Xor()
引数の省略、インプレース、戻り値
出力先の画像やマトリクス (dst
として表わされることが多い) が省略され たとき、それが補える場合は補うようにしています。補える例とそうでない例の 両方を示します。
my $dst = $src->Add($src2);
my $dst = $src->Add($src2, $mask); # can't omit dst
後者は、マスクとして与えた $mask
と出力先を区別することができません。 このような場合には $dst
を呼び出し元で用意してください。$dst
が $src
と同じなら次のとおり。
my $dst = $src->Add($src2, $src->new, $mask);
OpenCV は、インプレース処理が可能な関数では出力先の画像やマトリクス dst
に NULL
を指定し、入力画像を出力先としても使います。Cv
で はこの NULL
を表わすために \0
を使います。次の例は左右反転した画 像を返します。
my $dst = $src->Flip(\0);
OpenCV の関数は、この Flip() に限らず、出力先は呼び出し元が用意します。 そうした使い方では特に戻り値を使う必要はありません。しかし、上述のとお り Cv
では出力先を省略できるので、その場合にはメソッドの中で必要に応 じて作られた出力先を戻り値として受けとることになります。
この出力を戻り値として受けとる方法は、次の例のとおり、メソッドをつない で書けるようにしてくれますが、メソッドが呼ばれる度にオブジェクトの確保 と開放があるので、その分だけオーバヘッドがあります。
my $bin = $src->cvtColor(CV_RGB2GRAY)->threshold(...);
Cvで追加されたメソッド
(これはプログラムで生成したい。書くのは疲れる)
エラー処理
eval { ... } で保護したブロックの中のエラーを検出できるようになりました。 (Cv-0.13)
my $img = eval { Cv->createImage([-1, -1], 8, 3) };
if ($@) {
print STDERR "*** got error ***";
}
ただし、Cv
をインストールするとき、c++ でコンパイルしておく必要があります。 エラーを掴まえるだけでなく、自前で用意したエラー処理に向けることもできます。
Cv->redirectError(
sub { my ($status, $funcName, $errMsg, $fileName, $line, $data) = @_;
...
},
my $data = ...;
);
エクスポート
Cv によってインポートされる名前は、use Cv の後に指定できます。(Cv-0.14)
次の 2行は、CV
や IPL
ではじまる定数やマクロと cvScalarAll() のようないくつかの関数をインポートします。
use Cv qw(:std);
use Cv; # 何も指定しないとき :std が補われる
次の 2行は、Cv のすべての名前をインポートします。
use Cv qw(:all);
use Cv qw(/^(CV|IPL|cv)/);
何もインポートしないときは、空のリストを続けます。
use Cv qw( );
ヒント
Cv を使っている方から、ちょっといい使い方を教えて戴きました。
Cv で作成した画像を CGI で直接出力するとき、 EncodeImage() と Ptr() を使うことができます。 画像をファイルに保存する必要がありません。
use Cv; my $img = Cv::Image->new([240, 320], CV_8UC3); $img->zero->circle([ 100, 100 ], 100, CV_RGB(255, 100, 100)); print "Content-type: image/jpg\n\n"; print $img->encodeImage(".jpg")->ptr;
これは Imager 向けの変換にも使えます。
use Imager; my $imager = Imager->new(data => $img->encodeImage(".ppm")->ptr);
Inline C
を使うためのコンフィギュレーションを用意しました。 これは、いろいろな実験や拡張を容易にしてくれます。 使い方は次のとおり簡単です。use Cv::Config; use Inline C => Config => %Cv::Config::C;
サンプル
OpenCV に付属しているサンプルを、いくつか Cv
で書き直しました。 sample/
にあります。
-
bgfg_codebook.pl calibration.pl camshiftdemo.pl capture.pl chamfer.pl contours.pl convexhull.pl delaunay.pl demhist.pl dft.pl distrans.pl drawing.pl edge.pl facedetect.pl fback_c.pl ffilldemo.pl find_obj.pl fitellipse.pl houghlines.pl image.pl imager.pl inpaint.pl kalman.pl kmeans.pl laplace.pl lkdemo.pl minarea.pl morphology.pl motempl.pl mser_sample.pl polar_transforms.pl pyramid_segmentation.pl squares.pl stereo_calib.pl stereo_match.pl tiehash.pl video-thread.pl watershed.pl
バグ
バージョン 0.07 で名前付きの引数を諦めました。 名前付きの引数を処理するためのオーバヘッドが大きかったからです。 この版では
Cv::TieHash
とCv::TieArr
も削除しました。Cv::TieHash
はsample/tiehash.pl
を参照してください。バージョン 0.14 で別名を整理しました。 CV_MAKETYPE() のようなマクロのいくつかには Cv::MAKETYPE() のような別名もありましたが、もとの名前の方が短いので、 別名を止めることにしました。
バージョン 0.16 で
Cv
を分け、拡張したコードを分離して Cv::More に置くことにしました。バージョン 0.17 で typemap の見直しを。一旦、xlib も止める。
参考
http://sourceforge.net/projects/opencvlibrary/
著作権
Yuta MASUDA <yuta.masuda@newdaysys.co.jp>
Copyright (c) 2010, 2011, 2012 by Yuta MASUDA.
All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.