特定画像認識

find_object_2dパッケージを使用し,画像から所望の物体を検出します.

目的

前回の講義で扱ったARマーカー認識は,簡単かつ高精度にARマーカーを検出,さらには位置及び姿勢を認識できる便利なパッケージです. しかしながら,物体にARマーカーを貼ることができない場合には利用することができません. このような場合には,一般環境下で撮影した画像から認識したい物体を見つけるという処理が必要です. 今回はfind_object_2dパッケージを使用し,画像から所望の物体を検出します.

find_object_2dを用いた物体認識

find_object_2dパッケージでは,カメラで撮影した画像(入力画像)から予め用意した画像(テンプレート画像)を見つけることができる便利なパッケージです. 検出アルゴリズムは,入力画像及びテンプレート画像から注目画素周辺の領域に多くの濃淡情報を持つ特徴点(キーポイント)を検出し,特徴点周辺の領域から濃淡情報を数十から数百次元のベクトルとして数値化した記述子を抽出します. そして,2枚の画像から計算した記述子の類似度を求めることでキーポイントを対応づけます. これにより,入力画像中のどこに,どのぐらいの大きさでテンプレート画像が存在するかを認識できます. また,特長として画像の回転やスケール変化に不変,照明変化等にも頑健です.

SIFTに代表されるような特徴点の検出や記述の方法はSURF,FAST,BRIEF等があります. ここでは詳細なアルゴリズムの説明は省略します,気になる方は論文や解説記事を参考にしてください. find_object_2dパッケージでは画像処理ライブラリであるopencvに実装されているアルゴリズムを利用しています.

インストール

find_object_2dパッケージをインストールします.

1
$ sudo apt install ros-humble-find-object-2d

実行

find_object_2dを実行する前にROS2でカメラを使えるようにします.

1
$ ros2 run v4l2_camera v4l2_camera_node

次に,find_object_2dパッケージのノードを起動します. こちらのノードでは画像データを/imageという名前で購読する必要があるため,ノードを起動する際にトピック名を変更します.

1
$ ros2 run find_object_2d find_object_2d image:=/image_raw

上記のコマンドを実行すると下記のようなウィンドウが起動します. 実行結果1

画面左がテンプレート画像(初期の状態では空です),右がカメラから取得した画像です. 画像中の黄色い点はキーポイントを表します. テクスチャ(模様)の情報が多いトランプの絵柄から多くのキーポイントが検出できていることが確認できます.

画像中からクローバの13のカードを検出するためにテンプレートを登録します. 画面左のObjectsと書かれた領域で右クリックすると,メニューが表示されます. 今回は画像に写ったトランプをテンプレートとするため,Add object from scene...を選択します.

実行結果2

テンプレートを登録する小さなウィンドウが表示されます. 登録したいものが写った状態でTake pictureをクリックしてください.

実行結果3

映像が停止して,Take pictureをクリックした瞬間の画像が表示されます. テンプレートとして登録した領域をドラッグし,Nextをクリックしましょう.

実行結果4

ドラッグした領域が表示されます. ドラッグした領域に複数のキーポイントが含まれているか確認してください. キーポイントの数が多ければ多いほど,安定した検出ができるようになります. 問題なければEndをクリックします.

実行結果6 画面左に登録したテンプレートが表示され,画面右の映像からテンプレート画像を検出します. 下記の画像の場合,12は物体のID,括弧内の100はキーポイントの数, 68はマッチングしたキーポイント数,109マッチングしなかったキーポイント数を表しています. マッチングしたキーポイント数が多いほど正確に検出できるため,画面右の検出枠が安定します.

実行結果7

初期の状態では,SIFTと呼ばれる特徴点検出,特徴量記述子を用いて画像を認識するように設定されています. SIFTは,画像の回転やスケール(大きさ),明るさの変化に対応できるため,トランプの位置を変えても安定した検出されます.

実行結果8

また,一部分が隠れても幾つかのキーポイントが検出されれば,画像を認識することが可能です. ただし,マッチングしたキーポイントの位置関係から位置と大きさを推定するため, マッチングしたキーポイントの数が少ないと認識結果が不安定となります.

実行結果9

ノードとトピックの確認

コマンドラインツールを利用してノードやトピック等の情報を確認しましょう. まずはノードを確認します.

1
2
3
$ ros2 node list 
/find_object_2d
/usb_cam

カメラから画像を取得するノードが/usb_cam,画像認識を行うノードが/find_object_2dとなります. ノード名が分かったのでノードの情報を確認します.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
$ ros2 node info /find_object_2d 
/find_object_2d
  Subscribers:
    /image_raw: sensor_msgs/msg/Image
    /parameter_events: rcl_interfaces/msg/ParameterEvent
  Publishers:
    /info: find_object_2d/msg/DetectionInfo
    /objects: std_msgs/msg/Float32MultiArray
    /objectsStamped: find_object_2d/msg/ObjectsStamped
    /parameter_events: rcl_interfaces/msg/ParameterEvent
    /rosout: rcl_interfaces/msg/Log
    /tf: tf2_msgs/msg/TFMessage
  Service Servers:
    /find_object_2d/describe_parameters: rcl_interfaces/srv/DescribeParameters
    /find_object_2d/get_parameter_types: rcl_interfaces/srv/GetParameterTypes
    /find_object_2d/get_parameters: rcl_interfaces/srv/GetParameters
    /find_object_2d/list_parameters: rcl_interfaces/srv/ListParameters
    /find_object_2d/set_parameters: rcl_interfaces/srv/SetParameters
    /find_object_2d/set_parameters_atomically: rcl_interfaces/srv/SetParametersAtomically
  Service Clients:

  Action Servers:

  Action Clients:

/find_object_2dはカメラから取得した画像トピック/image_raw:を購読し, 複数のトピックを配信していることがわかります. 認識結果は/objectsという名前のトピックで配信されています. トピック/objectsのメッセージ型を調べてみましょう.

1
2
3
4
ros2 topic info /objects
Type: std_msgs/msg/Float32MultiArray
Publisher count: 1
Subscription count: 0

このメッセージ型が配信する情報を調べます.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
$ ros2 interface show std_msgs/msg/Float32MultiArray 
# This was originally provided as an example message.
# It is deprecated as of Foxy
# It is recommended to create your own semantically meaningful message.
# However if you would like to continue using this please use the equivalent in example_msgs.

# Please look at the MultiArrayLayout message definition for
# documentation on all multiarrays.

MultiArrayLayout  layout        # specification of data layout
	#
	#
	#
	#
	#
	MultiArrayDimension[] dim #
		string label   #
		uint32 size    #
		uint32 stride  #
	uint32 data_offset        #
float32[]         data          # array of data

少し分かりにくいですが,認識結果はdataに入ります. 最後にトピックをコマンドラインツールで購読します.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
$ ros2 topic echo /objects
layout:
  dim: []
  data_offset: 0
data:
- 13.0
- 121.0
- 176.0
- 0.8610056638717651
- -0.05650526285171509
- 0.0008222997421398759
- 0.0028126586694270372
- 0.46643751859664917
- -0.0007393158739432693
- 106.66329956054688
- 129.73094177246094
- 1.0

テンプレート画像を認識すると上記のようにトピックが確認できます. dataの中は順番に,物体のID,認識物体の横方向の大きさ(画素数),縦方向の大きさ,3x3のホモグラフィー行列となります. ホモグラフィー行列は平面を射影変換するための行列です. ホモグラフィー行列により認識した物体(認識した物体の矩形)の変形度合いを表すことができます.

コマンドラインツールで調べた情報を利用して,作成したシステムに組み込むことができます.

GUIを使わない方法

上記の方法で特定の画像を認識することが可能ですが,GUI操作を伴うとシステムに組み込むことが難しくなります. find_object_2dでは,パラメータを設定することでGUIを使わずに動作させることができます. GUI操作によるテンプレートの登録ができないため,事前に登録した状態のセッション情報をGUIで保存しておき,実行に引数でセッション情報を与えます. 具体的には,session_pathというパラメータにセッションファイル(今回はcard.bin),guiというパラメータにfalseを与えます.

1
$ ros2 run find_object_2d find_object_2d image:=image_raw  --ros-args -p session_path:="/home/yuu/card.bin" --ros-args -p gui:=false

ウィンドウにより認識結果を確認することができないため分かりにくいですが,先ほどと同様にtopic echoにより認識結果を確認することができます.