0904_Map_Auto_Ref-01【非公開勉強用】
OpenCVで学ぶ画像認識

 

OpenCVで学ぶ画像認識

1. 画像認識の基本を知ろう

1.1 この連載の目的

1.2 画像認識って何?

1.3 画像に関する研究分野

1.4 画像認識・理解の基本原理

1.5 身の回りにある画像認識・理解の技術

1.6 終わりに 

2. OpenCVを使ってみよう

2.1 OpenCVとは?

2.2 開発環境の構築

2.3 画像を表示してみよう

2.4 画像処理関数を使う

2.5 終わりに

3. オブジェクト検出してみよう

3.1 オブジェクト検出の仕組み

3.2 顔検出プログラム

3.3 終わりに

4. オブジェクト検出器の作成方法

4.1 学習の流れと仕組み

4.2 オブジェクト検出器の学習

4.3 オブジェクト検出プログラムの実行

4.4 連載の終りに

OpenCVで学ぶ画像認識

1. 画像認識の基本を知ろう

1.1 この連載の目的

最近,デジカメの顔検出機能などで,私たちにとって身近になりつつある画像認識技術ですが,Web技術など他のIT技術と比べてしまうと,まだまだ研究色の強い分野です。そのため,本当に自分で一から動くものを作ろうとしたら,数学などの専門知識が必要になります。

そこで,この連載ではOpenCVという便利なツールを使いながら,プログラミング知識以外の専門知識を必要としない形で,画像認識技術について解説していきたいと思います。

第1回目の今回は,画像認識技術の概要について解説します。

1.2 画像認識って何?

そもそも画像認識とはなんでしょうか?

この連載を読んでいる方には説明不要かもしれませんが,画像というのはコンピュータ上では,全て「ピクセル」という単位で扱われています。コンピュータは,「このピクセルは赤,このピクセルは青,……」ということは理解しているのですが,「この画像には人の顔が映っている」というのは理解できません。このようにコンピュータに画像に何が映っているのかを理解させるのが,画像認識技術になります。いわば,人間が当たり前に行っている視覚の機能をなんとかコンピュータに持たせようという研究分野とも言えます。

図1 コンピュータの理解している画像

画像の内容をコンピュータに理解させるためには,ピクセルの集合からなんらかのパターンを抽出しなくてはなりません。つまりピクセルを個別に見ていくのではなく,一つの集合として見て,その集合が持つパターンによって,画像が何を表しているのかを判断する必要があります。

このように,信号のパターンから意味を抽出することを「パターン認識」と呼びます。「パターン認識」は画像認識だけでなく,音声認識や言語解析など,ある信号から意味を抽出する処理全般を指します。

1.3 画像に関する研究分野

画像認識技術は,学会などでは「コンピュータビジョン」という分野の中で扱われています。有名な学会としては,毎年アメリカで開催されるCVPR(IEEE Computer Society Conference on Computer Vision and Pattern Recognition)や2年に一度開催されるICCV(IEEE International Conference on Computer Vision)などがあり,日本でも電気情報通信学会や情報処理学会などで盛んに研究が行われています。

先ほど,画像認識技術は画像に何が映っているのかをコンピュータに理解させることだと書きましたが,この「理解」にも2通りあります。一つはその画像が「何」であるかを何らかのシンボル(例えば「顔」「自動車」「文字」のような単語)として表したり分類したりする方法。もう一つはステレオカメラや動画像,画像の陰影などから,画像に映っているオブジェクトやシーンを三次元モデルとして復元する方法です。画像認識と言う場合は前者をさし,後者は画像理解や三次元復元などと呼ばれます。

また,「画像処理」という言葉もこれらの用語と混同して使われることが多いですが,これも意味が少し異なります。画像処理には認識は含まず,例えば画像をぼかしたり,逆に輪郭などのエッジ部分を強調したり,モザイクをかけたりといった,画像を変換して別の画像を作成する処理のことをさします。

図2 画像処理の例(エッジ抽出)

図3 画像認識の例(顔認識)

図4 画像理解の例(三次元復元)

コンピュータビジョンという言葉は主に「画像理解」をさすようですが,コンピュータビジョンの学会や論文誌などでは,これら画像認識,画像理解,画像処理が全て扱われてます。実際,例えば画像処理によって画像から特徴を抽出して認識を行ったり,画像認識の結果を元に画像理解を行うなど,3つの領域がお互い深く関係し合っています。

表1 画像処理・認識・理解

用語意味
画像処理画像に対して数学的な変換処理をかける
画像認識画像をパターンに基づいて認識・分類する
画像理解画像(2次元)から,被写体の三次元情報を復元する

この連載では,この表で言う画像認識技術を主に扱いますが,どの技術も非常に活発に研究されており,様々な分野で実用化されています。

1.4 画像認識・理解の基本原理

1.4.1 画像認識の基本原理

画像認識は,学習のフェーズと認識のフェーズの2つからなります。学習のフェーズでは,コンピュータに認識させたい対象画像を学習させる処理を行い,認識のフェーズではコンピュータに入力画像が学習した対象かどうかを判定させます。

図5 学習と認識の流れ

(1)学習フェーズ

学習のフェーズでは,まず画像になんらかの処理を施して,ピクセルのデータ列から,より学習に適したデータ列(特徴量データ)へと変換を行います。

次に変換されたデータを,機械学習と呼ばれるアプローチを用いてコンピュータに学習させます。機械学習とは,その名の通り人間が行っているような学習の仕組みをコンピュータに持たせるための技術です。例えば人間は,初めて見る人の顔画像でも,それが「顔」だとわかりますが,コンピュータはあくまでピクセルデータとして画像を処理してますので,今まで学習された画像のピクセルデータと同じかどうかは判定できても,それが「顔」と呼ばれるものかどうかは判定できません。機械学習を用いれば,入力データ群の中から共通のパターンや判別ルールなどを抽出でき,これにより学習データ以外の未知のデータに対しても,ルールに基づいたなんらかの判定ができるようになります。

(2)認識フェーズ

認識のフェーズでは,学習フェーズで用いたものと同様の手法で入力画像を特徴量データへ変換します。そして,変換されたデータを機械学習で抽出された判別ルールに基づいて,そのデータが何を表しているかを判別します。

画像認識の用途によっては,認識対象に関する知識を認識フェーズのアルゴリズムの中に内包させることで,学習フェーズを省いてしまうものもあります。例えば単純に円や直線などを画像から検出したい場合は,円や直線の数式を認識アルゴリズムの中に埋め込んでしまうので,学習フェーズは特に必要ありません。

また,学習画像の中から入力画像と最も近い画像を探してやりたいといった場合は,機械学習を使わなくても学習画像の特徴量と入力画像の特徴量との距離を計算することで,欲しい結果を得ることができます。

なお,機械学習を用いた画像認識のより具体的な方法については,今後の連載の中で触れていきたいと思います。

1.4.2 画像理解の基本原理

画像理解の基本原理は,「三角測量の原理」です。

下の図のように,2台のカメラで同じ対象を撮影したとします。対象上の点Aは,カメラ1で撮影した画像とカメラ2で撮影した画像とでは,それぞれ見える位置が異なります。2つのカメラの位置とそれぞれのカメラの焦点距離がわかっていれば,点Aのそれぞれのカメラでの見え方の違いから,点Aの三次元的な位置を計算することが可能です。

このような手法はステレオビジョンと呼ばれており,ほとんどの三次元復元技術はこの技術を応用したものになります。

図6 ステレオビジョンの原理

実は人間もこれと同じ原理で,両目で見ることによって対象までの距離を測っています。片目だと距離感が掴みづらくなるのはこれが原因です。

ただし,三次元復元を行うためには,必ずしもカメラが2台以上必要なわけではなく,例えば動画像を用いることでカメラが複数台ある場合と同じ原理で復元を行うこともできます。また,カメラの位置や焦点距離などの情報が未知であったとしても,対象上の点がそれぞれのカメラのどこに見えているかの対応を取ることができれば,それらのパラメータを計算することが可能です。

ステレオビジョンの原理以外でも,三次元復元を行う方法は色々と研究されています。例えば撮影対象の影の状態から三次元復元を行うShape from Shadingと呼ばれる方法や,撮影対象に関する事前知識を用いることで1枚の屋外画像や顔画像の三次元復元を行うような研究も存在します。

1.5 身の回りにある画像認識・理解の技術

画像認識・理解の技術は長らく,工場などの産業用に使用されることが多かったのですが,近年コンシューマ市場にも多く見られるようになってきました。ここではその一部をご紹介したいと思います。

1.5.1 OCR

おそらく,もっとも古くからコンシューマ市場で利用されている技術は文字認識技術でしょう。スキャナを購入すればほとんどの場合,OCRソフトウェアが一緒についてきます。

また,ZaurusなどのPDAにも,タッチペンで文字が入力できるようにOCRが組み込まれています。

なお,最近ではGoogleがOCRを使用した画像タギングに特許を申請したり,Evernoteというネット上に自分に関するあらゆるメモを残そうというコンセプトのソフトにおいて,自分のアップした画像をOCRで文字認識してインデックスをつけてくれるなど,従来の使い方とは違った,インターネットと組み合わせた使われ方が注目を集め出しています。

【参考:グーグル、画像内テキストを認識および利用する技術特許を申請】

Googleは、画像や映像に含まれるテキストの認識および利用に関する技術の特許を申請した。

 特許申請自体は2007年6月に行われたが、申請の内容は米国時間1月3日に発表された。Googleによると、この特許は「抽出した画像内のテキストを利用するための方法、システム、装置に関するもので、それらの中にはコンピュータプログラム製品も含まれる」という。

 申請書の要約では、「ある実行例の中には、コンピュータを使って実行する方法が挙げられる。この方法は、1つ以上の画像検索語の入力を受け、入力された1つ以上の検索語からキーワードを発見することを含む。また、この方法には、キーワード群、例えば画像内のテキストから抽出されたキーワードを検索し、1つ以上の画像検索語に対応する抽出された画像テキストに関連する画像を選び出し、その画像を表示することも含まれる」と述べられている。

Googleは、ネット上で最も広く利用されている画像検索機能だけでなく、主要なビデオ共有サイト「YouTube」をもすでに所有している。そのため、画像や映像に含まれるテキストを正確に読み取ることが可能になれば、同社にとっては大きなメリットだ。この機能の可能性としては、より正確なキーワードの作成やファイルの自動タギングなどが考えられる。また、背景に写っている文字から、その写真がどこで撮影されたかを特定することも可能だ。

 Googleの広報担当者は7日、特許申請に関する質問に答えたが、回答はごく標準的な内容だった。広報担当者は、「われわれは、従業員が思い付いた多様なアイデアに関する特許申請を行う」とした上で、「これらのアイデアの中には、後に実際に製品やサービスになるものもあれば、そうでないものもある。特許を申請したからといって、必ずしも将来製品として発表されるわけではない」と語った。

 Googleが光学式文字認識(OCR)の分野に踏み込んだのは、今回の特許申請が初めてではない。現在、OCR技術は主に文書をワープロで読み込み可能なフォーマットに取り込むために用いられている。

Googleは2006年9月に、(もともとHewlett-Packardが開発した)「Tesseract」と呼ばれる旧式OCRエンジンのデバッグを支援し、それをオープンソースとしてリリースした。当時、Googleは「一流のOCR専門エンジニア」を採用したいという希望も述べていた。

【参考:Evernote

Remember everything.

Evernote allows you to easily capture information in any environment using whatever device or platform you find most convenient, and makes this information accessible and searchable at any time, from anywhere. Did we mention that it's free?

Capture what you like, find it when you want

Stop forgetting things. Capture everything now so you will be able to find it all later.

Things to capture:

Tasks and to-dos

Notes and research

Web pages

Whiteboards

Business cards

Scribbles

Snapshots

Wine labels

Even Twitter messages

And then find them all any time across all the computers and devices you use.

New Premium feature: Add, sync, and access any file on any device or platform. Learn more about Evernote Premium »

How does Evernote do it?

Three steps:

01 You capture the things you want to remember using what you already use—your Windows or Mac computer, the web, and your mobile phone.

02 We run everything through our recognition technology, and then synchronize it across your devices. You can then organize and tag the notes, if you wish.

03 When you want to find something, just search or filter and there it is just like you remember it.

On the web. On your desktop. On your phone. In the cloud.

Everything you put into Evernote is always synchronized across all of your devices. That way, all your memories are available to you wherever you are.

1.5.2 デジカメ,顔ちぇき!

ここ数年で急速に実用化が進んだのが顔認識技術です。今やデジタルカメラに顔認識に基づいたオートフォーカスや画像補正は当たり前の機能になりました。最近は顔を検出するだけでなく,笑顔を検出する機能も提供されているのは皆さんご存知のとおりです。

また,手前味噌で恐縮ですが,弊社ジェイマジックで展開している「顔ちぇき!~誰に似てる?~™」は顔を認識するだけでなく,それが誰であるのかと言う「顔認証」の機能を応用して,ユーザの顔が有名人の誰と似ているかを判定してくれるモバイルサイトです。それまでは入退出管理などセキュリティ用として研究されてきた顔認証機能をエンターテイメントに応用することで多くの利用者を得ることができました。

図7 『顔ちぇき!』画面イメージ

1.5.3 広告キャンペーン

雑誌や看板などの印刷媒体を携帯電話のカメラで撮影すると,その画像が何かを認識して,画像に合わせたキャンペーンサイトへ誘導するというマーケティング手法が,様々なところで導入されています。

これは,あらかじめデータベースに登録した画像とカメラで撮影された画像が同一かどうかを判別する,オブジェクト認識という技術を使うことで実現されています。

これまた,弊社サービスで恐縮ですが,弊社の画像認識プラットフォーム「SAYL™」は,このようなキャンペーン向けにも多数使用されています。

参考:
サンスターのブランド認知キャンペーンに提供(IT Media)
またジェイマジック以外でも,携帯カメラを使用したオブジェクト認識のソリューションとして,インデックスソリューションズの「PicLin」,D2Cとバンダイの「ERサーチ」,NTTデータの「パッとび」,ゼータブリッジの「フォトナビ」などを各社が提供しています。
1.5.4 映画・ゲーム

モーションキャプチャという技術は皆さんも聞いたことがあるのではないでしょうか? 体にマーカーをつけることで,人間の三次元的な動きを正確にコンピュータに取り込む技術で,映画やゲームの世界では昔から使われています。特に最近の三次元ポリゴンでキャラクターを表現するリアル指向のゲームでは,モーションキャプチャを使うのは当たり前になりました。最近では,マーカーをつけずに人体の動きを取り込む技術も開発されつつあります。

参考:
東芝のマーカレスモーションキャプチャについて(IT Pro)

また,映画「Matrix」で,主人公ネオがエージェントスミスの弾丸を避ける有名なシーンを覚えてますでしょうか。ネオが弾丸を避けた瞬間動きが止まり,カメラがぐるっとネオの周りを回りますが,これはImage Based Renderingと呼ばれる,複数枚の画像からその画像間の三次元的な視点を復元する技術を使用しています。

参考:
Image Based Rendering by Paul Devebec (SIGGRAPH'97)(YouTube)
1.5.5 車載カメラ

自動車にカメラを載せて,道路の白線を検知をしたり,歩行者を検知したりといったドライバー支援の技術は,ITS(高度道路交通システム)などの分野で長いこと研究されていましたが,最近は市販の自動車にも搭載されるまでになりました。

例えば,トヨタのレクサスには,駐車のための駐車枠検出や,ドライバーの脇見運転検知,ステレオカメラによる障害物検知などが搭載されています。

1.6 終わりに 

というわけで,今回は画像認識・理解の技術について,その概要と実用例を解説しました。次回以降はOpenCVという画像処理ライブラリを使って,実際にプログラミングを通して画像認識を学んでいきましょう。

2. OpenCVを使ってみよう

第1回では,画像認識の概要や基本原理,実例などを紹介しました。第2回の今回は,これから皆さんが画像認識のプログラムを組んでいく上で必要なOpenCVというツールについて紹介します。

2.1 OpenCVとは?

OpenCVは正式名称を"Intel Open Source Computer Vision Library"と言い,その名のとおりインテル社が開発したオープンソースのC/C++ライブラリ集で,コンピュータ・ビジョンに必要な各種機能がパッケージされています。

具体的には,だいたい以下の処理を行う関数群が用意されています。

  • 線形代数や統計処理など,コンピュータビジョンに必要な各種数学関数
  • 直線や曲線,テキストなど画像への描画関数
  • OpenCVで使用したデータを読み込み/保存するための関数
  • エッジ等の特徴抽出や画像の幾何変換,カラー処理等々の画像処理関数
  • 物体追跡や動き推定などの動画像処理用関数
  • 物体検出などのパターン認識関数
  • 三次元復元のためのカメラ位置や姿勢の検出などのカメラキャリブレーション関数
  • コンピュータにパターンを学習させるための機械学習関数
  • 画像の読み込みや保存,表示,ビデオ入出力などインターフェース用関数

このように,OpenCVはどちらかというとビジョンの研究者や開発者の仕事を楽にするためのツールです。 OpenCVがなかった頃は,ビジョン関係の開発者は,画像フォーマットを解析して画像を読みこむプログラムやGUI上に表示するプログラム,画像をぼかしたり特徴のあるピクセルを強調するような「フィルタリング」と呼ばれる処理を,全て一から書かなくてはいけませんでした。しかし,OpenCVのお陰でそれらの処理を一から書かなくても済むようになり,開発が大変楽になりました。

もちろん,コンピュータ・ビジョンの専門知識がない人でも,例えばエッジを抽出したり,ぼかしたりといった画像処理プログラムを,このライブラリを使うことで簡単に組むことができます。

ただし,これらのライブラリ群を使ったとしても,例えば画像認識や画像理解(三次元復元)のようなプログラムを一から書こうとすると,専門知識なしに開発するのは難しいかもしれません。というのは,これらのライブラリの関数群はあくまで画像認識や画像理解などで共通して使用する処理をまとめたものであって,これらをどう組み合わせて,例えば顔を検出するプログラムを作るかは,結局開発者に委ねられているからです。

ただし,これには例外があります。実はOpenCVには,画像の中から物体を検出してくれる画像認識のプログラムが既に用意されているのです。この連載では,皆さんにこのプログラムを使いこなすことで,自分で物体検出アプリケーションを開発できるようになってもらうことを目指します。

2.2 開発環境の構築

この連載では,以下のような開発環境をベースに解説を行っていきます。

  • バージョン:OpenCV 1.0
  • OS:Winodows XP
  • IDE:Microsoft Visual C++ 2005

ただしOpenCVはLinuxやMac OS Xもサポートされてますし,もちろん他のIDE(例えばEclipse CDT)などでもコーディング可能です。以降の説明は,皆さんの開発環境にあわせて内容を解釈しながら読み進めてください。

2.2.1 ダウンロードとインストール

OpenCVはsourceforgeからダウンロード可能です。

入手先
URLhttp://www.sourceforge.net/projects/opencvlibrary

2008年5月現在の最新版はバージョン1.0です。こちらのサイトからWindows用のOpenCV_1.0.exeというファイルをダウンロードします。chopencv-2.5.0-win-binary.zipというファイルは今回使用しません。こちらはChと呼ばれるインタープリタ型C/C++言語プラットフォーム用のものです。

図1 ダウンロード

ダウンロードしたら,OpenCV_1.0.exeを実行してインストールを開始してください。指示に従えば簡単にインストールできると思います。

2.2.2 環境設定

では,次に開発環境を構築します。

開発環境は,インストールしたOpenCVのインクルードファイルのディレクトリへパスを張り,リンク先にOpenCVの各ライブラリを加えるだけで簡単にできます。

まずはVisual C++で新規プロジェクトを作成します。メニューバーの「ファイル」から"新規作成->プロジェクト"と選択し,「Win32 コンソール アプリケーション」のプロジェクトを作成して,適当なプロジェクト名をつけて下さい。

なお,プロジェクト作成の際,「追加のオプション」から「プリコンパイル済みヘッダー」のチェックボックスを外しておいてください。

プロジェクトが作成できたら,メニューバーの「プロジェクト」からプロパティを選択してください。

「構成」で「すべての構成」を選択し,左側のツリーから「C/C++」タブを選択し,「追加のインクルードディレクトリ」にインストールしたOpenCVのホームディレクトリの下の以下のディレクトリを追加します。

図2 インクルードディレクトリの設定

今度は,ライブラリへのリンクをはります。「リンカ」タブを選択し,「追加のライブラリディレクトリ」にOpenCVディレクトリ下の"lib"ディレクトリを追加して下さい(例:C:\Program Files\OpenCV\lib)。

続いて,「構成」を「Debug」に変更し,「リンカ」タブを展開した中の「入力」を選択し,「追加の依存ファイル」で"cxcore.lib cv.lib highgui.lib cvaux.lib"を追加します。

図3 ライブラリの設定

以上で設定は完了です。詳細なマニュアルなどは,インストールディレクトリのdocsディレクトリ以下にあるので参照して下さい(例:"C:\Program Files\OpenCV\docs")。

また,リファレンスマニュアルの日本語訳が以下のサイトで見ることができます。

参考:
OpenCVリファレンスマニュアル(日本語訳)


【OpenCVをインストールするには?】

インストールガイドをお読み下さい.

【OpenCVを早く習得するには?】
  • サンプルプログラム集(samplesディレクトリ内にあります)をご覧下さい.             OpenCVサンプルコード   物体検出(顔の検出)
  • お使いの開発環境に合ったOpenCVワークスペース(_makeディレクトリ内にあります)をロードしてください.Microsoft Visual Studio 6.0用は,opencv.dsw
    • Miscrosoft Visual Studio .NET 2003用は,opencv.sln
    • Borland C++ BuilderX用は,cbuilderx/opencv.bpgr (訳注:ver.1.0では存在しない)
    プロジェクトcvsampleを開き,ビルドして実行してください. コードを見て,適宜改変してみてください.
  • リファレンスマニュアル(docs\index.html)もご覧下さい.この中にも多くのサンプルが含まれています.
  • OpenCVアーカイブhttp://groups.yahoo.com/group/OpenCV から興味のあるトピックを探してください.
  • 新しいプロジェクトを一から作るか,既存のcvsampleを改変しましょう. OpenCVを使うための Microsoft Visual Studio のウィザードが http://groups.yahoo.com/group/OpenCVにあります. (Files sectionには,OpenCV@yahoogroups.com へのユーザ登録が必要です)
  • 【CXCORE リファレンス マニュアル】
    【CV リファレンス マニュアル】

    【機械学習 リファレンス マニュアル】

    【HighGUI リファレンス マニュアル】

    【CVAUX リファレンス マニュアル】

    【参考技術】

    ・Google (haar-like特徴量

     Haar-like 特徴とは、画像における特徴量として、照明条件の変動やノイズの影響を受けやすい各画素の明度値をそのまま用いるのではなく、近接する2 つの矩形領域の明度差を求めることで得られる特徴量である。

      Haar-like 特徴量は、矩形領域の平均明度の差分値として求められるスカラ量であり、その値は明度勾配の強度を表します。

    長所:絶対的な明度値に依存せず、テクスチャに相当する特徴量を抽出することができるという利点がある。

      Haar-Like特徴とは、図2の様な白黒で表される矩形特徴を用いて、対象となる画像の明度差を特徴量とする手法である。


    2.3 画像を表示してみよう

    それでは,いよいよコーディングに入ります。なお,以下の説明の中で使用している画像は,OpenCVのインストールディレクトリ以下の"\samples\c\lena.jpg"をコードのあるディレクトリへコピーして使用しています。

    まずは,画像をファイルから読み込み,表示するプログラムを書いてみましょう。

    【画像の読み込み・表示プログラム】

    #include "cv.h"
    #include "highgui.h"
    
    int main(int argc, char* argv[])
    {
     IplImage* img; // 画像ファイルポインタの宣言
     char imgfile[] = "lena.jpg"; // 読み込み画像ファイル名
    
     // 画像の読み込み
     img = cvLoadImage(imgfile, CV_LOAD_IMAGE_COLOR);
    
     // 画像の表示
     cvNamedWindow ("lena", CV_WINDOW_AUTOSIZE);
     cvShowImage ("lena", img);
     cvWaitKey (0);
     cvDestroyWindow("lena");
    
     // 画像の解放
     cvReleaseImage(&img);
    
     return 0;
    }

    まず始めの2行で"cv.h"と"highgui.h"をインクルードします。

    次に画像領域を宣言します。IplImageというのが,OpenCVで使用される画像を表す構造体になります。この構造体には,画像の横幅や縦幅,画像のデータ型,チャネル数など画像を表すのに必要なデータが全て入っています。

    cvLoadImage関数で,IplImage構造体に画像データを読み込みます。

    OpenCVで読みこむことのできるファイルフォーマットは以下のとおりです。

    • Windows bitmaps - BMP, DIB
    • JPEG files - JPEG, JPG, JPE
    • Portable Network Graphics - PNG
    • Portable image format - PBM, PGM, PPM
    • Sun rasters - SR, RAS
    • TIFF files - TIFF, TIF
    • OpenEXR HDR images - EXR
    • JPEG 2000 images - jp2

    次に読みこんだデータを表示させます。

    cvNameWindowでは,表示させるためのウィンドウを作成します。第1引き数はウィンドウの識別に用いられる名前です。ウィンドウのタイトルバーに表示されます。

    次に,cvShowImageで,読みこんだ画像を先ほど作成したウィンドウに読みこんで表示させています。cvWaitKeyは,何かキーが押されるまで待つという意味です。

    最後にcvDestroyWindowでウィンドウを廃棄し,cvReleaseImageで読みこんだ画像のメモリ領域を解放します。

    では,コンパイルして実行してみましょう。ウィンドウが開いて,指定した画像が表示できれば成功です。

    2.4 画像処理関数を使う

    さて,画像を読みこんで表示させることはできました。次はこれに,なんらかの画像変換の処理を加えます。

    2.4.1 エッジ抽出処理

    では,手始めに画像から階調変化の強い箇所(エッジ)を抽出してみましょう。OpenCVには何種類かのエッジ抽出関数が用意されていますが,ここではCannyのアルゴリズムと呼ばれているものを使うことにします。

    【エッジ抽出プログラム】

    #include "cv.h"
    #include "highgui.h"
    
    int main(int argc, char* argv[])
    {
     IplImage* img; // 入力画像ポインタ
     IplImage* img2; // 出力画像ポインタ
     char imgfile[] = "lena.jpg"; // 読み込み画像ファイル名
    
     // 画像の読み込み
     img = cvLoadImage(imgfile, CV_LOAD_IMAGE_GRAYSCALE); // グレースケールで読み込み
     img2 = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1); // 画像のメモリ領域割り当て
    
     // エッジ抽出
     cvCanny(img,img2,64,128);
    
     // 画像の表示
     cvNamedWindow ("lena", CV_WINDOW_AUTOSIZE);
     cvShowImage ("lena", img2);
     cvWaitKey (0);
     cvDestroyWindow("lena");
    
     // 画像の解放
     cvReleaseImage(&img);
     cvReleaseImage(&img2);
    
     return 0;
    }

    前回のプログラムと違うポイントとしては,まずcvLoadImageによって入力画像を呼び出す際,"CV_LOAD_IMAGE_GRAYSCALE"という引数を与えることで,モノクロ画像として抽出しています。

    また,今回は出力の画像ポインタimg2を用意し,それに対しcvCreateImageという関数を用いて領域確保を行っています。

    1番目の引き数は画像の縦サイズと横サイズを指定しており,ここではcvGetSize関数を使って入力と同じサイズを割り当てています。2番目の引き数は1ピクセルあたりのデータ型指定で,"IPL_DEPTH_8U"は8bitのUnsigned型(つまり0から255までの値を持つ)を表しています。3番目の引き数の1は,1ピクセルあたりのチャネル数で,ここではモノクロ画像なので1を指定しています。もしカラー画像を使用したい場合は,R,G,Bの三種類のチャネルを容易する必要があるため,この引き数は"3"になります。

    エッジ抽出は,cvCanny関数で行います。1番目と2番目の引き数にそれぞれ入力と出力の画像を指定し,3番目と4番目にはエッジ抽出のための弱い閾値と強い閾値の2つを指定します。この2つの閾値はここでは,エッジらしさを2段階で評価している,程度に考えていただければ結構です。

    さて,このコマンドを実行した結果,下の図のような結果が出れば成功です。

    図4 エッジ抽出結果

    2.4.2 画像の幾何学変換

    次は画像の幾何学的な変換について,画像を回転させる方法を例に説明します。

    【画像回転プログラム】

    #include "cv.h"
    #include "highgui.h"
    
    int main(int argc, char* argv[])
    {
     IplImage* img; // 入力画像ポインタ
     IplImage* img2; // 出力画像ポインタ
     char imgfile[] = "lena.jpg"; // 読み込み画像ファイル名
    
     CvMat* rotationMat; // 回転行列
    
     // 画像の読み込み
     img = cvLoadImage(imgfile, CV_LOAD_IMAGE_COLOR); // カラーで読み込み
     img2 = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3); // 画像のメモリ領域割り当て
    
     // 回転行列領域の確保
     rotationMat = cvCreateMat(2,3,CV_32FC1);
    
     // 30度の回転行列を求める
     cv2DRotationMatrix(cvPoint2D32f(img->height/2,img->width/2),30,1,rotationMat);
    
     // 回転
     cvWarpAffine(img,img2,rotationMat);
    
     // 画像の表示
     cvNamedWindow ("lena", CV_WINDOW_AUTOSIZE);
     cvShowImage ("lena", img2);
     cvWaitKey (0);
     cvDestroyWindow("lena");
    
     // 画像の解放
     cvReleaseImage(&img);
     cvReleaseImage(&img2);
     
     cvReleaseMat(&rotationMat);
    
     return 0;
    }

    画像の回転は,数学的には行列の計算で求めることが出来ます。つまり画像はピクセル値を数値と見なした行列と考え,それに対して回転行列をかけることで,画像を回転させます。

    まず回転行列をCvMat型のrotationMatととして宣言します。ここで,cvCreateMat関数を用いて2×3の行列領域を確保します。CV_32FC1とは,行列の1要素が32ビット浮動小数点型であるという宣言です。

    次にcv2DRotationMatrixを用いて,回転行列を求めます。1番目の引き数では回転の中心位置を指定しています。ここでは,画像の中心を回転の中心としたいので,入力画像の縦幅と横幅の半分の値をcvPoint2D32f関数で浮動小数点型の点座標に変換しています。

    2番目の引き数が,回転させたい角度です。ここでは30度とします。

    3番目の引き数が,拡大/縮小を行う比率です。ここでは拡大/縮小は行わないため1としています。

    4番目の引き数が出力先の先ほど領域を確保したrotationMatです。

    ここで取得できた回転行列を元に,cvWarpAffine関数で画像変換を行います。cvWarpAffine関数は,画像の幾何学変換を行うための関数です。入力画像,出力画像,回転行列をそれぞれ引き数に入れることで,回転画像を得ることができます。

    さて,このコマンドを実行した結果,下の図のような結果が出れば成功です。

    【図5 画像回転結果】

    2.5 終わりに

    というわけで,今回はOpenCVについて,画像処理のプログラムを動かすまで行いました。OpenCVには他にもボカシや二値化など,様々な画像処理関数が用意されてますので,OpenCV付属のマニュアルを見ながら、ぜひ色々と試して見て下さい。

    次回はいよいよ,画像から顔を検出するプログラムの作成と,その仕組みについて解説したいと思います。

    3. オブジェクト検出してみよう

    第1回第2回と画像認識の基礎とOpenCVについて紹介してきました。第3回目の今回は,いよいよ本連載の目玉であるOpenCVを使ったオブジェクト検出に挑戦してみます。

    3.1 オブジェクト検出の仕組み

    3.1.1 基本原理のおさらい

    オブジェクト検出のプログラムを書き始める前に,そもそもどんな仕組みでオブジェクト検出を行っているのかを理解しましょう。 第1回では画像認識の原理として,学習フェーズと認識フェーズがあることを説明しましたが,OpenCVに実装されているオブジェクト検出プログラムもこの流れに従います。つまり,画像から特徴量を抽出し,学習アルゴリズムによってオブジェクトを学習します(詳しくは第1回を参照してください)。

    図1 画像認識の流れ

    OpenCVに実装されているオブジェクト検出プログラムは,Paul Violaらのオブジェクト検出の研究[1]をベースに,Rainer Lienhartらが改良した研究[2]が実装されています。これらの研究では,画像特徴量としてHaar-Like特徴量,学習アルゴリズムとしてAdaboostと呼ばれるアルゴリズムを使用しており,非常に高速にオブジェクト検出が行えます。

    なお,以下で説明するアルゴリズムは,考え方を伝えるためにかなり乱暴に簡略化しています。詳しいやり方に興味のある方は,以下の原著を読んでみてください。

    3.1.2 Adaboost

    OpenCVのオブジェクト検出器は,学習にAdaBoost(エイダブースト,またはアダブースト)と呼ばれる方法を用いています。 AdaBoostは一つひとつはあまり判別能力の高くない(ただしランダムに判定するよりは若干ましという程度の)弱い識別器を,たくさん繋げることで強い識別器を作るという考え方の,学習・判別アルゴリズムです。強い識別器は,弱い識別器をその重要度にあわせて重みをつけて,それらを組み合わせたものになります。

    図2 Adaboostの概要

    例えば,ある画像が車かどうかを判断する識別器を作りたいとします。車かどうかを判定させるために,画像中に丸があるかを判断する識別器や,三角があるかを判断する識別器,四角があるかどうかを判断する識別器など,単純な図形に反応する複数の識別器を用意したとしましょう。

    ここに車の画像を入力したところ,タイヤなどのせいで丸を判定する識別器が強い出力を返しました。その場合,丸を判定する識別器は車かどうかを判定する上で重要なので,重みを重くします。次に車以外の画像を入力(例えばオニギリの画像)した際,三角の識別器が反応したとします。この場合は三角の識別器の重みを小さくします。

    このような処理を繰り返すことで,車を入力すると強く反応し,車以外を入力すると反応しない強い識別器を作成することができます。

    このように,正解画像と非正解画像,及び教師信号(画像が正解画像か不正解画像かを教える信号)を与えて学習をさせると言うやり方はほとんどの機械学習で一般的な方法です。

    3.1.3 弱識別器とHaar-Like特徴量

    それでは次に,画像からどのような特徴量を取得するかを考えます。OpenCVのオブジェクト検出器で用いている特徴の例を下の図に示しました。

    図3 オブジェクト検出特徴の例

    入力画像上の任意の場所に,図のような検出窓をおいた場合,検出窓の中の画像の特徴量は,以下の式で計算されます。

    特徴量 = 矩形特徴の黒領域の画素値の合計 - 矩形特徴の白領域の画素値の合計

    この矩形領域の白黒パターンはHaar-Like(ハールライク)特徴と呼ばれるもので,以下のパターンを用意しています。

    図4 矩形領域のパターン

    このように,検出窓内の矩形の位置とパターンの組み合わせによって,約12万通りのオブジェクト検出特徴が用いられます。 この特徴パターン一つ一つが,AdaBoostの弱識別器の役割を果たします。

    例えば,オブジェクト検出特徴を顔画像の上においた場合を考えます。

    図5 検出特徴を顔に適用したの例

    通常の顔画像では,目の領域の画素は周辺よりも暗いと考えられるので,上図のような検出特徴の特徴量は高くなることが予想されます。このような特徴に対しては,AdaBoostによって強い重みがつけられます。

    このような検出窓で画像中をスキャンして,その都度強い識別器で判別していくことで,オブジェクトの検出を行うことができます。

    なお,Haar-Like特徴はちょっとした工夫で非常に早く計算することが可能です。このHaar-Like特徴を用いたことと,次に説明するAttentional Cascadeを用いたことにより,OpenCVのオブジェクト検出プログラムはリアルタイムに動作することができます。

    3.1.4 Attentional Cascade

    通常,検出窓で画像内をスキャンした場合,オブジェクトがみつかるよりもオブジェクト以外が見つかる方がはるかに確率が高いです。そのため,"いかに非オブジェクトの検出窓を拒否するか"というのが高速化の鍵になります。

    そこでOpenCVのオブジェクト検出では,ここまでの説明で作成した強い識別器を複数連結(カスケード)することで,精度と速度を改善しています。

    図6 Attentinal Cascade

    この図のように識別器を連結させたものを,Attentional Cascadeといいます。

    画像上にある検出窓を設けた時,1つめの識別器で非オブジェクトと判断されたものは,それ以上の処理は行われずに終了します。もし,1つめでオブジェクトとして判断された場合は,2つめの識別器へ渡されます。同様に,2つめの識別器で非オブジェクトであると判断されたものは弾かれ,それ以外の画像が3つめの識別器へ渡されます。

    つまり,上流の識別器では緩い判断基準で次々と疑わしい画像を排除していき,下流にいくほどオブジェクトの判断基準が厳しくなるように調整されています。

    これらの識別器は,12万個の特徴パターンのうち,通常上流ほどわずかな数の特徴パターンを使用しているため,高速に非オブジェクト画像を弾くことできます。

    以上が,OpenCVで用いられているオブジェクト検出の仕組みになります。

    3.2 顔検出プログラム

    というわけで,ようやく実際のオブジェクト検出プログラムの話に入ります。OpenCVにはあらかじめ,学習された「顔」情報が用意されているため,まずはこれを使用して顔検出プログラムを書いてみましょう。

    下のプログラムで使用されている,学習済み顔画像”haarcascade_frontalface_default.xml”は,OpenCVインストールディレクトリ下の”data\haarcascades”にありますので,コピーをするかプログラム中でパスを指定するようにしてください

    【顔検出プログラム】

    int main(int argc, char* argv[])
    {
     /* 画像のロード */
     char imgfile[] = "office.jpg";
     IplImage* image = cvLoadImage( imgfile, 1 );
    
     /* 正面顔検出器のロード */
     CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_default.xml" );
    
     CvMemStorage* storage = cvCreateMemStorage(0);
     CvSeq* faces;
     int i;
    
     /* 顔検出 */
     faces = cvHaarDetectObjects( image, cascade, storage );
    
     /* 顔領域の描画 */
     for( i = 0; i < faces->total; i++ )
     {
     /* extract the rectanlges only */
     CvRect face_rect = *(CvRect*)cvGetSeqElem( faces, i );
     cvRectangle( image, cvPoint(face_rect.x,face_rect.y),
     cvPoint((face_rect.x+face_rect.width),
     (face_rect.y+face_rect.height)),
     CV_RGB(255,0,0), 3 );
     }
    
     /* 画像の表示 */
     cvReleaseMemStorage( &storage );
     cvNamedWindow( "face_detect", 0 );
     cvShowImage( "face_detect", image );
     cvWaitKey(0);
     cvReleaseHaarClassifierCascade( &cascade );
     cvReleaseImage( &image );
    
     return 0;
    }

    重要なポイントだけ解説致します。まず,

    CvHaarClassifierCascade* cascade = (CvHaarClassifierCascade*)cvLoad( "haarcascade_frontalface_default.xml" );

    で,正面顔を学習させたカスケード識別器とそのパラメータをXMLファイルから読み込みます。”haarcascade_frontalface_default.xml”が学習済みの顔データになります。OpenCVで用意されている構造体などの情報は,cvLoadやcvSaveによって簡単にファイルへの読み込み/書き込みが可能です。

    次にcvHaarDetectObjects()関数を使って画像から検出し,facesにというCvSeq構造体ポインタへ検出した顔の位置情報を渡します。

    最後に,cvGetSeqElem関数で,facesから一つ一つ顔領域を矩形データとして取得し,それをcvRectangle()で描画します。

    実行の結果,次のような結果が出れば成功です。

    図7 顔検出結果

    3.3 終わりに

    いかがだったでしょうか? 今回は,OpenCVで用いられているオブジェクト検出アルゴリズムと,実装の仕方について解説しました。画像認識が具体的にどのような流れで行われているのかのイメージを掴んでいただけたら幸いです。

    次回は,いよいよ最終回。自分たちでコンピュータに対してオブジェクトを学習させることで,オリジナル検出器を作ってみましょう。

    4. オブジェクト検出器の作成方法

    今回はいよいよ最終回です。前回はオブジェクト検出器を使って顔を検出するところまで行いました。今回は,オリジナルオブジェクト検出器を作成してみます。

    今回作成するプログラムのソースコードは,こちらから一括してダウンロードすることができます。

    4.1 学習の流れと仕組み

    4.1.1 学習の流れ

    前回のおさらいになりますが,オブジェクト検出器は機械学習という方法を通して作成されます。つまり,コンピュータプログラムに検出したいオブジェクトの画像(正解画像)とそうでない画像(非正解画像)を与えることで,オブジェクトが含まれている画像の傾向というのをコンピュータに覚えさせていきます。

    学習の流れを簡単にまとめると以下の通りです。

    1. 正解サンプル画像と非正解サンプル画像を用意する
    2. サンプル画像のリストファイルをそれぞれ作成する
    3. 正解サンプル画像を元に,学習用正解ファイルを生成する
    4. 学習用正解ファイルと非正解リストファイルを元に,学習を行う

    ここで解説する学習方法の詳細については,インストールディレクトリ下の"apps/HaarTraining/doc/haartraining.htm"を参照して下さい。

    今回は,画像の中から下図のような技術評論社のロゴを抽出するプログラムを作成します。

    図1 技術評論社ロゴ

    4.1.2 学習の仕組み

    第3回で解説したとおり,OpenCVのオブジェクト検出はAdaBoostで学習させた強識別器を複数連結(カスケード)したものになっています。

    図2 Attentional Cascade

    検出器の学習は,この1番目の強識別器から順番に進めていきます。

    各ステージ(強識別器の学習)には,目標とする認識率(正解画像を正解と判断した率)及び許容できる誤認識率(非正解画像を正解と誤って判断した率)があり,それを達成するまで繰り返し矩形特徴(弱識別器)を追加しながらAdaBoostによる学習を行っていきます。

    全体が目標とする認識率,及び誤認識率を達成した時点で学習は終了です。

    このように,学習は多くの繰り返し処理を必要とするため,非常に時間がかかります(早くて数時間,長いと数日から数週間)。

    学習時間は,全学習ステージ数(標準で14),目標とする認識率,学習データの数などによって左右されますので,必要に応じて調整してください。

    4.2 オブジェクト検出器の学習

    4.2.1 画像の収集

    まず,正解画像と非正解画像をそれぞれ収集します。

    OpenCVのドキュメントによると,学習に用いる上で効率的なサンプル数は,正解画像7000枚,非正解画像3000枚とのことですが,ここでは正解画像4000枚,非正解画像1700枚程度で行います。

    それだけ大量の画像をどこから集めるかですが,インターネット上には様々な画像素材提供サイトがあるので,そこから探すというのも一つの手です。またコンピュータ・ビジョンの研究分野では,実験用に顔画像やオブジェクト画像を提供している研究室がたくさんあるので,そういったデータを利用するのも良いかもしれません。

    いくつか例としては,

    MITの顔画像データ
    カリフォルニア工科大学のオブジェクト画像データ

    などがあります。

    なお,正解画像を集める方法には2通りあります。一つは頑張って例えば自分でデジカメで撮影したり,インターネットから学習画像を集めること。もう一つは,1枚の画像に対して回転や変形などを加えることで,学習画像を増やす方法です。前者は顔や自動車など,個人差(車種)や表情などで形が変形するものに対して有効な方法で,後者はロゴなど形が一定のものを見つけたい時に適用します。

    ここでは,後者の方法を用いて技術評論社のロゴを検出するプログラムを作成する予定ですが,前者についても解説します。

    画像を収集したら,それを記述するリストファイルを作成します。

    例として,下の図のようなディレクトリに非正解画像が入っている時,非正解画像のリストファイルは以下のような形式で書かれたテキストファイルになります。

    図3 ディレクトリ構造例

    【非正解画像リストファイル(NG.txt)の例】

    NG\image_0001.jpg
    NG\image_0002.jpg
    NG\image_0003.jpg
    NG\image_0004.jpg
    NG\image_0005.jpg

    一行一行に,作業ディレクトリからの画像ファイルへの相対パスが記述してあります。

    同様の要領で,正解画像のリストファイルを作成します。ただし,ロゴ等の1枚の画像からツールで複数の正解画像を作成したい場合は,リストファイルの作成は必要ありません。

    【正解画像リストファイル(OK.txt)の例】

    OK\image_0001.jpg 1 120 100 45 45
    OK\image_0002.jpg 2 100 200 50 50 50 30 25 25 
    OK\image_0003.jpg 1 40 55 60 60
    OK\image_0004.jpg 1 104 98 40 40
    OK\image_0005.jpg 2 62 70 50 50 120 162 30 30

    非正解画像のリストと違うのは,相対パスのファイル名の後に,数字が並んでいることです。

    これは,画像中のオブジェクトの位置を表しています。OpenCVのオブジェクト検出では,検出窓で画像中をスキャンして,その窓の中にオブジェクトがあるかどうかを判定していくアルゴリズムで,学習もまたこの窓の単位で行われます(第3回参照)。そのため,学習の際には正確なオブジェクトの位置をプログラムに教えてやる必要があります。

    ファイル名の後ろにある数字は,その画像中に何個オブジェクトが含まれているかを示しています。その後,4つの数字がオブジェクトの座標を表し,最初の2つがオブジェクトを囲む矩形の左上の座標値(x,y),次の二つがそれぞれ幅と高さを表します。

    図4 オブジェクトの座標値

    では,次に収集した画像とリストファイルを用いて,学習用の正解ファイルを作成します。

    4.2.2 学習用正解ファイルの作成

    1枚の画像から大量の正解画像を作成するために,OpenCVでは"createsamples"というツールが用意されています。このツールを使って,ある一枚の正解画像から,ランダムに回転させたり,色を変えたり,任意の背景にオブジェクトを置くなどの処理を行った学習画像を作成することができます。

    まず,OpenCVインストールディレクトリのbinの下にある以下のファイルを作業用ディレクトリへコピーして下さい。

    • createsamples.exe
    • haartraining.exe
    • cv100.dll
    • cxcore100.dll
    • libguide40.dll
    • highgui100.dll

    次に,コマンドプロンプトを立ち上げて,作業用ディレクトリに移動し,以下のコマンドを実行します。

    > > createsamples.exe -img gihyo_logo.png -vec pos_gihyo.vec -num 4000 -bgcolor 255 -w 44 -h 18 -show

    createsamples.exeが1枚の正解画像から,たくさんの学習用サンプルを作るためのコマンドです。以下の各オプションを使っています。

    -img

    学習の元画像を示します。

    1枚の画像からではなく,集めたたくさんの学習画像から学習用正解ファイルを生成する場合,-imgの引数を-infoに変えて正解画像リストファイルを指定します。

    -vec

    出力ファイル名です。学習用画像データは全てこの1つのファイルにまとめられます。

    -num

    作成する学習サンプル画像の数です。ここでは4000を指定しました。

    -bgcolor

    背景色を示します。ただし単純にグレースケール画像の0から255までの濃度であらわします。この例ですと背景色は白なので255を指定します。

    -bg

    この例ではロゴの背景は一様である場合がほとんどなので使用していませんが,もし検出したいオブジェクトが,複雑な背景の中にある場合が予想されるなら,このオプションで前節で作成した非オブジェクト画像リストを記したテキストファイルを指定します。

    -w

    学習サンプル画像の横幅(ピクセル)を指定します。ここでは元画像の1/4のピクセルサイズを指定しました。

    -h

    学習サンプル画像の縦幅(ピクセル)を指定します。学習サンプル画像では,元の画像を回転させたものが生成されるため,その遊びを持たせるために元画像の1/2のサイズを指定しました。

    -show

    このオプションを指定すると,実際にどのようなサンプル画像が生成されたかを見ることができます。Windowが開いたらスペースキーを押すことで,次のサンプル画像を見ることができます。画像の閲覧をやめる場合はESCキーを押すか,ウィンドウを閉じてください。
    事前にどのような画像が生成されるかを見ることで,その他のオプションのパラメータを最適化することをお勧めします。

    他にも様々なオプションが用意されてますが,詳細はマニュアルを見て,対象に合わせてそれらのオプションを調整して下さい。

    これで,正解ファイルが作成できました。いよいよ次は学習に映ります。

    4.2.3 オブジェクトの学習

    オブジェクトの学習には,"haartraining"というツールを使用します。なお,以下の作業を行った際に,突然PCが落ちるなど,うまくいかない場合があるかもしれませんが,その際はソースからhaartrainingを再コンパイルするようにして下さい。

    学習を行うにはコマンドプロンプトから,次のように実行します。

    > > haartraining.exe -data gihyo_logo -vec pos_gihyo.vec -bg NG.txt -npos 4000 -nneg 1685 -w 44 -h 18 -mode ALL
    -data

    出力したい学習結果xmlファイル名です。同名の作業用フォルダが自動的に作成されます。

    -vec

    学習サンプルデータを指定します。

    -bg

    非オブジェクト画像リストを記したテキストファイルを指定します。

    -npos, -nneg

    それぞれ学習させる正解画像,非正解画像の枚数を指定します。

    -w, -h

    createsamplesで指定したものをそのまま使用して下さい。

    -mode

    使用するオブジェクト検出特徴の種類を指定します(第3回参照)。ここでは全ての種類の特徴を用いています。

    これにより学習がスタートします。このコマンドを実行すると,最終的にgihyo.xmlというxmlファイルが生成されます。これが,オブジェクトパターンを表したデータになります。

    学習の進捗は以下のように,画面上に表示されます。

    【学習の様子】

    記の表の"node"または"stage"が一つの強識別器にあたります。この画面の例では2つの強識別器まで学習が終わっており,stage 2を親ノードとする3番目の強識別器が,3つの矩形特徴(弱識別器)を用いて学習が終わったところです。

    もし計算時間がかかりすぎて途中で止めたいときは,Ctrl-Cなどで強制終了して下さい。再度haartraining.exeを同じオプションで実行すれば,学習が終わったステージから学習が再開されます。

    表のNというのは,そのステージの強識別器の学習に要している弱識別器の数で,一つ一つ増やしながら目標となる認識率や許容できる誤認識率を達成するように調整を繰り返していきます。学習によっては,このNの回数が増え続けていつまでたっても終わらないという場合があります。これは,現在の学習データではどのようにパラメータを調整しても,なかなか目標値を達成できないということであり,その場合は学習画像の数やcreatesamplesのパラメータを調整するなどして,再度チャレンジした方が良いかもしれません。

    4.3 オブジェクト検出プログラムの実行

    では,本連載の第2回を参考にオブジェクト検出プログラムを作成して下さい。顔学習データ"haarcascade_frontalface_default.xml"の代わりに,今回学習させたxmlファイルを指定するだけで,実行が可能です。

    図5 検出結果例1

    図6 検出結果例2

    このように,オリジナルのオブジェクト検出機を作成することができました。現時点で若干の誤認識がありますが、学習パラメータや学習画像を増やすなどして色々と試してみて下さい。

    4.4 連載の終りに

    これで4回にわたって行われた連載は終了です。この連載ではOpenCVのオブジェクト検出アルゴリズムを通して,皆さんに画像認識技術とはどういうものか,実感として少しでも伝えることを目的に始めました。

    そして一方で,画像認識技術が人間の認識能力と比べて非常に見劣りするものであることも感じたのではないかと思います。

    この分野はまだまだ発展途上の分野です。世界中の優れた研究者がしのぎを削って研究を行っており,次々と新しい手法が考案されています。認知科学や脳科学、数学、物理など他の分野からもどんどん新しい知見を取り入れています。この連載で扱ったアルゴリズムは画像認識の,さらにはコンピュータ・ビジョンという枠組みの中のごく一部でしかありません。

    今,IT技術はどんどんコモディティ化が進み,アイデアさえあれば誰でもサービスが作れるような時代がきつつあります。少なくとも一昔前に比べれば,開発のハードルは圧倒的に下がりました。

    それと比べると,画像認識の分野は誰もが簡単に開発できるほど技術が成熟してはいません。しかし,今後少しずつ一般の技術者でも使える画像認識技術が世の中に出てくると思います。OpenCVはそのための大事な一歩であることは確かです。

    そして僕は,成熟していない分野だからこそインターネットの黎明期のように,技術者にとって非常に魅力的なフロンティアが広がっていると思っています。