実例で学ぶPHP拡張モジュールの作り方

第3回 WEBカメラから画像をキャプチャ

この記事を読むのに必要な時間:およそ 9.5 分

仕上げ

最後に,画像サイズの代入と変数の開放です。画像サイズを代入するのは第3引数が指定された(sizeがNULLでない)場合だけです。配列操作の解説は次回以降にしたいと思います。

リスト14 画像サイズの代入と変数の開放

if (size != NULL) {
  CvSize imgsize = cvGetSize(image); /* 画像サイズを取得 */
  zval_dtor(size);  /* 変数の中身を開放してから */
  array_init(size); /* 配列として初期化し直して */
  add_next_index_long(size, (long)imgsize.width);   /* 幅を追加 */
  add_next_index_long(size, (long)imgsize.height);  /* 高さを追加 */
}

cvReleaseCapture(&capture); /* imageも同時に開放される */
efree(fullpath);
RETURN_TRUE; /* 戻り値をtrueにしてreturn */

これでcv_camera_capture()の実装は終わりました。cv_file_capture()の実装はcv_camera_capture()と共通の部分がほとんどなので省略します。

インストール

実装が終わったら,いよいよcvcaptureモジュールをビルドします。pkg-configを使っているので,configureのオプションでOpenCVのインストール先を指定する必要はありません。cv_file_capture()のテストをしたい場合は,適当な3GPP2形式の動画ファイルをsample.3g2という名前で作業ディレクトリにコピーしてください。

操作2 ビルド&テスト

$ phpize
Configuring for:
PHP Api Version:         20041225
Zend Module Api No:      20060613
Zend Extension Api No:   220060519
$ ./configure --enable-cvcapture
(省略)
$ make
(省略)
Build complete.
Don't forget to run 'make test'.
$ make test
(省略)
=====================================================================
Running selected tests.
PASS cv_camera_capture() function [tests/cv_camera_capture.phpt] 
PASS cv_file_capture() function [tests/cv_file_capture.phpt] 
=====================================================================
Number of tests :    2                 2
Tests skipped   :    0 (  0.0%) --------
Tests warned    :    0 (  0.0%) (  0.0%)
Tests failed    :    0 (  0.0%) (  0.0%)
Tests passed    :    2 (100.0%) (100.0%)
---------------------------------------------------------------------
Time taken      :    2 seconds
=====================================================================

テストが通ることが確認できたら,あとはインストールするだけです。

操作3 インストール

$ sudo make install
Installing shared extensions:     /usr/local/lib/php/extensions/no-debug-non-zts-20060613/

実際に使ってみる

無事にインストールできたところで,実際に使ってみましょう。リスト15は1秒置きに10回カメラの画像をキャプチャするスクリプトです。出力する画像ファイル形式は拡張子から自動で決定されます。

OpenCVがサポートしていない拡張子が指定された場合や,カメラに接続できなかった場合などは「OpenCV ERROR:(理由)...」というエラーメッセージが表示され,プロセスが強制終了するので注意してください。この挙動は,あと数回に分けてcvcaptureモジュールを改良していくシリーズの最後で,OpenCVの例外をPHPの例外に変換することで対処します。

リスト15 サンプルスクリプト(cvcapture-sample.php)

<?php
extension_loaded('cvcapture') || dl('cvcapture.so');

for ($i = 1; $i <= 10; $i++) {
    cv_camera_capture(sprintf('capture%02d.jpg', $i));
    sleep(1);
}

図1はサンプルスクリプトの実行結果です。ちゃんと撮影できていますね。じっとしてくれない犬をMacBook内蔵のiSightカメラで撮影するために10回リピートしたという噂も聞かれますが,リピートしたのは次回へのフリでもあります。:-)

図1 キャプチャした画像

capture09

おわりに

今回は依存するライブラリの指定方法,定数の定義,戻り値や引数の指定,エラー出力,パスのチェックなど,多岐にわたる内容を紹介しました。詰め込みすぎのきらいは否めませんが,いずれも重要な項目です。

ところで,今回作成した関数cv_camera_capture()およびcv_file_caputure()は1回だけ使うなら便利なのですが,リスト15のように連続でキャプチャする場合は,呼び出される度にカメラに接続またはファイルを開くので処理の効率がよくありません。特に動画では最初のフレームしか取得できないという制限もあります。そこで,次回はcvcaptureモジュールにリソースのサポートを追加し,リソースを使って連続でキャプチャする関数を実装します。

サンプルファイルのダウンロード

著者プロフィール

関山隆介(せきやまりゅうすけ)

ジンガジャパン株式会社に所属。PHP拡張モジュールを作った数なら(たぶん)日本一。PHP 5.3に対応したものはPEARチャンネルGitHubで公開中。

URLhttp://d.hatena.ne.jp/rsky/