The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

名前

Cv - 何かコンピュータビジョンでやってみるとき、 あなたの助けになるように

概要

 use Cv;
 my $image = Cv->LoadImage("/path/to/image");
 $image->ShowImage("image");
 Cv->WaitKey;

説明

Cv は OpenCV コンピュータビジョンライブラリの Perl インタフェースです。 OpenCV はインテルで生まれ、 その後、皆の手によって素敵なライブラリとして成長を続けています。 そこには C/C++ だけでなく Python のインタフェースもありますが、Perl もあって良いと思いました。 Perl のスローガンに則り、簡単なことは簡単に、難しいこともそれなりに。 Cv の特徴は次のとおりです。

  • Cv は、OpenCV の C言語のリファレンスに合わせて作成しました。 詳細は http://opencv.itseez.com/ を参照してください。

  • コンストラクタとして Createなんとか() を使うことができます。

     my $img = Cv->CreateImage([ 320, 240 ], IPL_DEPTH_8U, 3);
     my $mat = Cv->CreateMat([ 240, 320 ], CV_8UC3);
  • コンストラクタに new を使うこともできます。 CreateImage() の代りに Cv::Image->new を、 CreateMat() の代りに Cv::Mat->new を使うことができます。 呼び出し形式について、 CreateImage() と CreateMat() は違いますが、 Cv::something->new を介した場合、違いはありません。 これは、Cv::Arr の中で、元のオブジェクトのことを知らないで 同じオブジェクトを作れるようにしています。

     my $color = Cv::Image->new([ 240, 320 ], CV_8UC3);

    引数は省略できます。省略したものは元のオブジェクトから引き継がれます。

     my $img2 = $img->new;
     my $img3 = $img->new(CV_8UC1);  # Cv::Image->new([240, 320], CV_8UC1)
  • OpenCV には画像を扱う型として IplImage*、 マトリクスを扱う型として CvMat*CvMatND*CvSparseMat* があります。 Cv ではこれらを Cv::ImageCv::MatCv::MatNDCv::SparseMat で bless したリファレンスで表わします。 それから、こうした画像やマトリクスを区別なく扱える Cv::Arr があります。 CvPointCvSize はメンバの値を並べた配列で表わします。 詳細は typemap を参照してください。

  • OpenCV は cvCreateImage() で割り当てたメモリを開放するために cvReleaseImage() を使いますが、 Cv ではオブジェクトが消滅するときに呼ばれる DESTROY の中で後始末をします。 そのため DESTROY は、しばしば cvReleaseなんとか() の別名として定義されています。 cvQueryFrame() のように開放できないポインタを返すものは、 Cv::なんとか::Ghost で bless して区別し、 オブジェクトの開放を抑止しています。

  • メソッドの名前は、OpenCV の関数名の頭の cv を省いた名前と、 名前のはじめの大文字を小文字に直したものが使えます。 次の 2つの例はどちらも cvCreateMat() を呼び出します。

     my $mat = Cv->CreateMat(240, 320, CV_8UC3);
     my $mat = Cv->createMat(240, 320, CV_8UC3);
  • 出力先の画像やマトリクス (dst として表わされることが多い) が省略されたとき、 それが補える場合には補うようにしています。

     my $dst = $src->Add($src2);
  • OpenCV は、インプレース処理が可能な関数では出力先の画像やマトリクス dstNULL を指定し、入力画像を出力先として扱います。 Cv ではこの NULL を表わすために \0 を使います。

     my $dst = $src->Flip(\0);
  • cvAdd()cvAddS() のような類似した関数は Add() にまとめました。メソッドの名前を変えて扱うデータを区別する必要はありません。

     my $dst = $src->Add($src2);        # cvAdd() を呼ぶ
     my $dst = $src->Add([ 1, 2, 3 ]);  # cvAddS()
  • 配列を扱う関数、たとえば FillConvexPoly() は点 CvPoint の配列を扱いますが、C言語は配列をその先頭のポインタで表すので、 別途、配列の大きさも渡さなければなりません。 Perl は配列の大きさも分るので、単に点の配列を渡すだけで十分です。 CreateMatND()FindCornerSubPix() 等も同様です。

  • cvMinMaxLoc() の類は与えられた変数に値を格納します。

     $src->MinMaxLoc(my $min, my $max);

    $min$max を呼び出し元に返すには、 stat() や localtime() のように戻り値の方が使いやすいかもしれませんが、 OpenCV のリファレンスに合わせました。

  • Inline C を使うためのコンフィギュレーションを用意しました。 これは、いろいろな実験や拡張を容易にしてくれます。 使い方は次のとおり簡単です。

     use Cv::Config;
     use Inline C => Config => %Cv::Config::C;

ヒント

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);
  • Perl のデータに Cv のヘッダを付けることができます。 行儀が良いとは言えませんが、 Cv で Perl のデータを直接操作できるようになります。

     my $data = pack("C*", 0 .. 255);
     my $mat = Cv::Mat->mew([16, 16], CV_8UC1, $data);
     substr($data, 0x41, 1) = 'x';
     print chr($mat->get([4, 1])->[0]), "\n";

サンプル

OpenCV に付属しているサンプルを、いくつか Cv で書き直しました。 sample/ にあります。

 bgfg_codebook.pl calibration.pl camshiftdemo.pl capture.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 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 watershed.pl

バグ

  • 進歩し続ける OpenCV の新しい機能が使いたくなったら、Cv のプロトタイプを xs に置いてください。 パッケージ Cv または Cv::Arr に配置できるときは、 名前の調整 (cv を取り除いたり、はじめの大文字を小文字に直したり) は AUTOLOAD が始末するため、橋渡しのコード以外に必要なものはありません。 それ以外のところでは、Cv::aliases を使うことができます。

  • 新しい定数が使いたくなったら Cv::Constant に書かなければなりません。

  • バージョン 0.07 で名前付きの引数を諦めました。 名前付きの引数には大きなオーバヘッドがあったからです。 この版では Cv::TieHashCv::TieArr も削除しました。 Cv::TieHashsample/tiehash.pl を参照してください。

参考

http://sourceforge.net/projects/opencvlibrary/

著作権

Yuta MASUDA <yuta.masuda@newdaysys.co.jp>

Copyright (c) 2010, 2011 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.