質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

AR(Augmented Reality)

AR(Augmented Reality)とは、拡張現実のことです。人が認識する現実の環境で視覚・聴覚などの知覚が感知する情報をコンピュータで拡張する技術、もしくはその環境そのものを表す言葉です。

Q&A

解決済

1回答

5105閲覧

Python,ArUcoを用いたARマーカの個別認識について

yamaneko0717

総合スコア6

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

AR(Augmented Reality)

AR(Augmented Reality)とは、拡張現実のことです。人が認識する現実の環境で視覚・聴覚などの知覚が感知する情報をコンピュータで拡張する技術、もしくはその環境そのものを表す言葉です。

0グッド

0クリップ

投稿2020/06/29 06:50

編集2020/07/16 02:07

「ArUco」ライブラリを使用して、マーカの認識を行っています。

他の方が公開されていたARマーカの認識プログラムを用いてマーカまでの距離、及び座標を計測しているのですが、複数マーカーを検出するとIDと距離及び座標の関係が混同してしまいます。

こちらのプログラムを、複数マーカを認識した際にそれぞれのマーカのデータを表示させるようにするためにはどこを変えればよいでしょうか。

ご回答お待ちしております。

質問追記2020/07/16
質問内容が分かりづらいとの事でしたので、内容の追記になります。
現在、カメラからARマーカまでの3次元座標系計測(カメラからのx,y,z座標計測)を行っております。
そこでマーカーの計測部分を下記参考サイト様のプログラムを用いて実施しております。
単独マーカの場合ではIDと3次元座標系のタグ付けが可能なのですが、複数マーカになると(ID)、(x,y,z座標)のデータを個別に出力することが出来ずカメラに移っているID番号と3次元座標データがランダムに1つ表示されてしまいます。
これを、たとえば(ID1のマーカ=(x1,y1,z1)),(ID2のマーカ=(x2,y2,z2))…のように表示させる方法があれば教えていただきたいです。

参考にさせていただいたリンク先↓
https://qiita.com/ReoNagai/items/a8fdee89b1686ec31d10

python

1import numpy as np 2import cv2 3from cv2 import aruco 4 5def main(): 6 cap = cv2.VideoCapture(0) 7 # マーカーサイズ 8 marker_length = 0.056 # [m] 9 # マーカーの辞書選択 10 dictionary = aruco.getPredefinedDictionary(aruco.DICT_ARUCO_ORIGINAL) 11 12 camera_matrix = np.load("mtx.npy") 13 distortion_coeff = np.load("dist.npy") 14 15 while True: 16 ret, img = cap.read() 17 corners, ids, rejectedImgPoints = aruco.detectMarkers(img, dictionary) 18 # 可視化 19 aruco.drawDetectedMarkers(img, corners, ids, (0,255,255)) 20 21 if len(corners) > 0: 22 # マーカーごとに処理 23 for i, corner in enumerate(corners): 24 # rvec -> rotation vector, tvec -> translation vector 25 rvec, tvec, _ = aruco.estimatePoseSingleMarkers(corner, marker_length, camera_matrix, distortion_coeff) 26 27 # < rodoriguesからeuluerへの変換 > 28 29 # 不要なaxisを除去 30 tvec = np.squeeze(tvec) 31 rvec = np.squeeze(rvec) 32 # 回転ベクトルからrodoriguesへ変換 33 rvec_matrix = cv2.Rodrigues(rvec) 34 rvec_matrix = rvec_matrix[0] # rodoriguesから抜き出し 35 # 並進ベクトルの転置 36 transpose_tvec = tvec[np.newaxis, :].T 37 # 合成 38 proj_matrix = np.hstack((rvec_matrix, transpose_tvec)) 39 # オイラー角への変換 40 euler_angle = cv2.decomposeProjectionMatrix(proj_matrix)[6] # [deg] 41 42 print("x : " + str(tvec[0])) 43 print("y : " + str(tvec[1])) 44 print("z : " + str(tvec[2])) 45 print("roll : " + str(euler_angle[0])) 46 print("pitch: " + str(euler_angle[1])) 47 print("yaw : " + str(euler_angle[2])) 48 49 # 可視化 50 draw_pole_length = marker_length/2 # 現実での長さ[m] 51 aruco.drawAxis(img, camera_matrix, distortion_coeff, rvec, tvec, draw_pole_length) 52 53 cv2.imshow('drawDetectedMarkers', img) 54 if cv2.waitKey(10) & 0xFF == ord('q'): 55 break 56 57 cv2.destroyAllWindows() 58 59if __name__ == '__main__': 60 main()

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aokikenichi

2020/07/12 06:20

「『ArUco』ライブラリ」というのを存じ上げません。「他の方が公開されていたARマーカの認識プログラムを用いて」であればそのリンク等も示したほうが回答を得られる可能性が高まると思います。 「複数マーカーを検出するとIDと距離及び座標の関係が混同してしまいます。 こちらのプログラムを、複数マーカを認識した際にそれぞれのマーカのデータを表示させるようにするためにはどこを変えればよいでしょうか。」 何を解決したいのかがよくわかりません。 例示しているプログラムは他の方が公開されていたプログラムそのままということでしょうか。 複数マーカのデータを表示させるためにご自身はどこまでトライして、どういう課題にぶつかったのでしょうか。 「混同してしまいます」では「落ち着いて丁寧にご確認ください」程度のアドバイスしかできません。
guest

回答1

0

ベストアンサー

detectMarkers関数について、公式ドキュメント

For each detected marker, it returns the 2D position of its corner in the image and its corresponding identifier.

と説明されていることから、

corners, ids, rejectedImgPoints = aruco.detectMarkers(img, dictionary)

の行について、(この関数を呼び出したときに返ってくる)corners配列内のデータ順序は、同ids配列内に格納されているマーカーIDの順序と対応しているものと思われます。

具体的には、この関数を呼び出す毎に返ってくる
ids[0,1,2,...n] と
corners[0,1,2,...n]
について、常に

マーカーID:ids[0] の 頂点データは corners[0]
マーカーID:ids[1] の 頂点データは corners[1]
・・・
・・・
マーカーID:ids[n] の 頂点データはcorners[n]

という風に格納されていると思われます。

よって、たとえば

for i, corner in enumerate(corners): (略) euler_angle = cv2.decomposeProjectionMatrix(proj_matrix)[6] # [deg] # 下を追加 print("ID{} のマーカー=(x: {}, y: {}, z: {}, roll: {}, pitch: {}, yaw: {})".format( ids[i], str(tvec[0]), str(tvec[1]), str(tvec[2]), str(euler_angle[0]), str(euler_angle[1]), str(euler_angle[2])))

とすれば、検知した各マーカーのID番号とそのIDに対応する座標・方向データが正しくprint出力されます。

補足

[1度の処理ループの中で例えばID1とID2のマーカが同時に見えているときに、それぞれの座標、方向データをprintする方法]

参照:自作サンプルコードのリンク

まず、取得した画像フレーム中に認識されているすべてのマーカーを一度辞書(markers)に格納します。
(サンプルコードの48行目から56行目)
(辞書のキー:マーカーID、値:各マーカーの座標・方向データ)

lang

1 if len(corners) > 0: 2 # マーカーごとに処理 3 for i, corner in enumerate(corners)  4 (略) 5 euler_angle = cv2.decomposeProjectionMatrix(proj_matrix)[6] # [deg] 6 # マーカーIDをキーにして、マーカーID毎の座標・方向を辞書に格納: 7 markers[ids[i][0]] = { 8 "x": str(tvec[0]), 9 "y": str(tvec[1]), 10 "z": str(tvec[2]), 11 "roll": str(euler_angle[0]), 12 "pitch": str(euler_angle[1]), 13 "yaw": str(euler_angle[2]) 14 }

そして、forループが終わった後(=1画像中に認識されている複数のマーカー全部の座標・方向データを取得し終わった後)に、
座標/方向データを格納した辞書markersの内容を一括してprint出力します。
(これが「1度の処理ループの中で複数のマーカが同時に認識されているときに、それぞれの座標、方向データをprintする」ということに相当します)

lang

1 # 1フレーム内にある複数マーカーの座標・方向を出力する。 2 if len(markers.keys()) > 0: 3 print('='*20) 4 for mid in markers.keys(): # マーカーIDを列挙 5 print("ID%s のマーカー=(x: %s, y: %s, z: %s, roll: %s, pitch: %s, yaw: %s)" % ( 6 mid, markers[mid]["x"], markers[mid]["y"], markers[mid]["z"], markers[mid]["roll"], markers[mid]["pitch"], markers[mid]["yaw"])) 7 sys.stdout.flush() 8 time.sleep(0.01) 9 print('='*20)

lang

1<出力結果例> 2==================== 3ID33 のマーカー=(x: 0.37299620897877683, y: 0.27564137297074015, z: 1.110049767074254, roll: [-179.21082782], pitch: [12.49320262], yaw: [-30.8981787]) 4ID303 のマーカー=(x: 0.06045913651229322, y: 0.09409733040784415, z: 0.37885871558283024, roll: [165.96844965], pitch: [11.57957246], yaw: [-32.58198751]) 5==================== 6==================== 7ID33 のマーカー=(x: 0.3782612414418004, y: 0.2739673617455094, z: 1.117224765870064, roll: [141.8837889], pitch: [8.68655973], yaw: [-30.71523192]) 8ID303 のマーカー=(x: 0.059853849602700245, y: 0.09263841265615678, z: 0.37457827584934494, roll: [166.37149935], pitch: [13.71420176], yaw: [-33.21705198]) 9====================

出力結果例で、「============」で囲まれている範囲それぞれが、各々の時点で同時に認識されているマーカーのデータになります。
(上記の出力結果では、ID33とID303のマーカーが同時に認識されていることを示しています)

投稿2020/07/16 11:07

編集2020/07/17 15:45
patapi

総合スコア820

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yamaneko0717

2020/07/17 03:03

ご回答いただき誠にありがとうございます! 追加で質問なのですが、1度の処理ループの中で例えばID1とID2のマーカが同時に見えているときに、それぞれの座標、方向データをprintしようと思うと for i, corner in enumerate(corners): ↑この部分を修正すればよいのでしょうか?
patapi

2020/07/17 15:45

回答後半に補足を追加しました。 結論から言うと、 for i, corner in enumerate(corners): は修正せず、データの格納方法を変えています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問