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

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

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

ARKitは、iPhone/iPad向けのARアプリ用フレームワーク。iOS11以降に標準搭載されています。これを用いたARアプリは、特殊なデバイスがなくてもiPhone/iPadの単眼カメラを使用して動作することが可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

Q&A

1回答

5503閲覧

Swift ARKitで空間の座標を取得し、それをiPhoneの画面内での座標に変換したい。

ccchogeee

総合スコア11

ARKit

ARKitは、iPhone/iPad向けのARアプリ用フレームワーク。iOS11以降に標準搭載されています。これを用いたARアプリは、特殊なデバイスがなくてもiPhone/iPadの単眼カメラを使用して動作することが可能です。

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

iPhone

iPhoneとは、アップル社が開発・販売しているスマートフォンです。 同社のデジタルオーディオプレーヤーiPodの機能、電話機能、インターネットやメールなどのWeb通信機能の3つをドッキングした機器です。

0グッド

0クリップ

投稿2020/11/05 08:22

編集2020/11/06 03:38

前提・実現したいこと

ARKitを使ってアプリを作っています。
ARFaceTrackingConfigurationで顔を映し、

let noseVertexID = 7 let noseVertex = faceAnchor.geometry.vertices[noseVertexID] nose.position = SCNVector3(noseVertex)

で鼻のワールド座標を返せるようになりました。
このとき、iphoneの画面内の鼻の座標を取得したいです。

最終的にやりたいことは、
画面内である範囲を指定し、その範囲の中に鼻が入っているかどうかを判断することです。

試したこと

func getScreenPointfromARPos(sceneView:ARSCNView , pos:SCNVector3) -> (x: Float, y: Float){ let screenPos = sceneView.projectPoint(pos) return (screenPos.x, screenPos.z) }

という関数を作成し、

let point = getScreenPointfromARPos(sceneView: sceneView,pos: nose.position) testLabel1.text = "point:x (point.x)" testLabel2.text = "point:y (point.y)"

というふうに使ってみました。
point.xとpoint.yで値は表示されるのですが、画面内に表示されている位置と値が合っていないような気がします。
たとえば、
view.frame.widthで画面の横サイズは414と分かったのですが、
point.xでは500やマイナスの値をとったりします。
画面上では同じあたりに鼻があっても、角度を変えたりすると値が大きく変わります。

わからないこと

ワールド座標をスクリーン座標に変換した値は、
iPhoneの画面内に表示されている(x, y)の位置とは違うのでしょうか。

よろしくお願いします。

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

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

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

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

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

guest

回答1

0

以下参考記事に記載のあるメソッドを利用すると、ワールド座標をスクリーン座標系に変換できそうです。
(少し試した感じだと近い値が取れていた様に思います)

・参考記事(「ワールド座標系 -> スクリーン座標系」 の項目参照)
ARKitのための3D数学

・メソッド

Swift

1func projectPoint(_ point: SCNVector3) -> SCNVector3

・参考例(ARSCNViewDelegateの"didUpdate"内に記載)

Swift

1func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) { 2 3 guard let faceAnchor = anchor as? ARFaceAnchor else { return } 4 5 let worldPosition = "対象のSCNNode".position 6 7 // "sceneView"は、利用しているARSCNViewの変数に適宜置き換える 8 let positionOnScreen = sceneView.projectPoint(worldPosition) 9 let x = positionOnScreen.x 10 let y = positionOnScreen.y 11 12 print("--------------------") 13 print("x: (x)") 14 print("y: (y)") 15}

投稿2020/11/05 15:11

編集2020/11/05 15:12
tsuki01

総合スコア1751

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

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

ccchogeee

2020/11/06 02:44

コメントありがとうございます!! わたしも、 func projectPoint(_ point: SCNVector3) -> SCNVector3 を使って、同じようにワールド座標をスクリーン座標にしていました! (上の質問内では、 func getScreenPointfromARPos(sceneView:ARSCNView , pos:SCNVector3) -> (x: Float, y: Float) { let screenPos = sceneView.projectPoint(pos) return (screenPos.x, screenPos.z) } を作成して使っていました!) しかし、view.frame.widthで出される画面の位置?とは、なんだかずれているように思い、、、 xcodeではiphone11を設定して使っており、 view.frame.widthで画面の幅が414、view.frame.heightで高さが896と分かりました。 UIimageview等も、この数値にしたがって配置できます。 しかし、スクリーン座標に変換した値をみてみると、端は(0, 0)とはならず、時にはマイナス、x軸方向に500を超える値が出てきたりします。 画面のサイズ(view.frame.widthで出される値)と、スクリーン座標系とは何かスケール?が違っているのでしょうか、、、 うまく伝わっていなかったら申し訳ありません!!!
ccchogeee

2020/11/06 02:56

すみません、ご回答的には上記の方法で問題なく変換できているということですよね、、、! ありがとうございます、、、!!
tsuki01

2020/11/06 03:16

>わたしも、 >func projectPoint(_ point: SCNVector3) -> SCNVector3 >を使って、同じようにワールド座標をスクリーン座標にしていました! 上記に関して大変失礼いたしました。見落としておりました。 こちらは3Dオブジェクト(SCNNode)から位置を算出していたのでマイナスの値とかが出なかったかもしれませんね(質問者さんはフェイスメッシュの位置情報から値を変換していますが、何か違いがあるのかどうか。。) 正確な回答が出せるか分からなくて申し訳ないのですが、念の為 "noseVertexID" としている値を質問文に追記できたりしますでしょうか?(鼻のあたりであれば、8〜9とかの値でしょうか)
ccchogeee

2020/11/06 03:39 編集

お返事ありがとうございます! let noseVertexID = 7 としてあります!鼻のてっぺんあたりです!追記もしておきます! 鼻のてっぺんが、画面内の指定した範囲内にあるかどうかを判断したいと思っていて、 画面内でのその(x, y)がわかればいいなと思っていますmm よろしくお願いします。
tsuki01

2020/11/06 16:35

「faceAnchor.geometry.vertices[noseVertexID]」から取得した位置情報をそのまま使おうとすると、やはり想定した動きにならないですね。。(お昼にコメントした様に、単純な3Dオブジェクトの位置情報からなら想定した動きになる) なので、geometryから位置情報を取得する時は何かしらの変換作業が必要なのかもしれません。 ※以下リンク先で書かれている様なことをSwiftで置き換えれたら実現可能かもしれませんが、私には直ぐに理解できそうになく。。回答しておいて解決できずに大変申し訳ありません。 ・参考リンク https://ringsbell.blog.fc2.com/blog-entry-1277.html
ccchogeee

2020/11/09 00:39

いろいろ考えていただきありがとうございます! サイト、みてみます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問