15

Kinect 深度マップから取得した 2 つの連続した 3D ポイント クラウド 1 および 2 (クラウド全体ではなく、OpenCV の GoodFeaturesToMatch を使用してクラウドから選択された 100 ポイントなど) を指定して、1 から 2 までのカメラのホモグラフィを計算したいと考えています。ここ (スライド 12)ここ (スライド 30)、そして古典的な論文のように見えるのはここです。私の問題は、私は有能なプログラマーですが、これらのメソッドの 1 つをコードに変換するための数学や三角関数のスキルがないことです。これは簡単な問題ではないため、次の問題を解決するコードに大きな報奨金を提供します。

カメラは原点にあり、Z 方向を見て、不規則な五面体 [A、B、C、D、E、F] にあります。 カメラ位置 1

カメラは左に -90mm (X)、上に +60mm (Y)、前方に +50mm (Z) 移動し、下に 5°、右に 10°、反時計回りに -3° 回転します。 カメラ位置 2

カメラが元の位置に戻るようにシーン全体を回転させると、2 の頂点の位置を特定できます。 ここに画像の説明を入力

これを準備するために使用される 3DS Max ファイルは、 max 1max 2およびmax 3です。

前後の頂点の位置、組み込み関数などは次のとおりです。 頂点と組み込み関数

camera2 の頂点は 100% 正確ではないことに注意してください。意図的なノイズが少し含まれています。

ここにExcelファイルの数値があります

私が必要とするコードは、必要に応じて EMGUCV と OpenCV を使用して、VB.Net または C# に容易に変換できる必要があり、2 セットの頂点と組み込み関数を取得し、次の出力を生成します。

Camera 2 is at -90 X, +60 Y, +50 Z rotated -5 Y, 10 X, -3 Z.
The homography matrix to translate points in A to B is:
a1, a2, a3
b1, b2, b3
c1, c2, c3

同次座標のホモグラフィが 3X3 なのか 3X4 なのかはわかりませんが、頂点を 1 から 2 に変換できるはずです。

また、a1、a2 などの値もわかりません。それはあなたが見つけなければならないものです>;-)

500 報奨金の提供は、私がこの非常によく似た質問に提供した報奨金を「置き換え」ます。この質問を指すコメントを追加しました。

EDIT2: この質問の仕方が誤解を招くものかどうか疑問に思っています。問題は、カメラ ジオメトリよりもポイント クラウド フィッティングにあるようです (A を B に変換および回転する方法を知っている場合は、カメラの変換とその逆を知っています)。もしそうなら、おそらく解はカブシュのアルゴリズムまたは同様のもので得られる可能性があります

4

3 に答える 3

1

同様のニーズを持つ人のために、Kabsch のアルゴリズムを使用して 3D ジオメトリの一部の移動と最適な回転を決定する部分的なソリューションを次に示します。

Imports Emgu
Imports Emgu.CV
Imports Emgu.CV.Structure
Imports Emgu.CV.CvInvoke
Imports Emgu.CV.CvEnum
Imports System.Math

Module Module1
    ' A 2*2 cube, centred on the origin
    Dim matrixA(,) As Double = {{-1, -1, -1},
                                {1, -1, -1},
                                {-1, 1, -1},
                                {1, 1, -1},
                                {-1, -1, 1},
                                {1, -1, 1},
                                {-1, 1, 1},
                                {1, 1, 1}
                               }
    Dim matrixB(,) As Double
    Function Translate(ByVal mat As Matrix(Of Double), ByVal translation As Matrix(Of Double)) As Matrix(Of Double)

        Dim tx As New Matrix(Of Double)({{1, 0, 0, 0},
                                         {0, 1, 0, 0},
                                         {0, 0, 1, 0},
                                         {translation(0, 0), translation(1, 0), translation(2, 0), 1}})
        Dim mtx As New Matrix(Of Double)(mat.Rows, mat.Cols + 1)

        ' Convert from Nx3 to Nx4
        For i As Integer = 0 To mat.Rows - 1
            For j As Integer = 0 To mat.Cols - 1
                mtx(i, j) = mat(i, j)
            Next
            mtx(i, mat.Cols) = 1
        Next

        mtx = mtx * tx
        Dim result As New Matrix(Of Double)(mat.Rows, mat.Cols)
        For i As Integer = 0 To mat.Rows - 1
            For j As Integer = 0 To mat.Cols - 1
                result(i, j) = mtx(i, j)
            Next
        Next
        Return result
    End Function
    Function Rotate(ByVal mat As Matrix(Of Double), ByVal rotation As Matrix(Of Double)) As Matrix(Of Double)
        Dim sinx As Double = Sin(rotation(0, 0))
        Dim siny As Double = Sin(rotation(1, 0))
        Dim sinz As Double = Sin(rotation(2, 0))
        Dim cosx As Double = Cos(rotation(0, 0))
        Dim cosy As Double = Cos(rotation(1, 0))
        Dim cosz As Double = Cos(rotation(2, 0))
        Dim rm As New Matrix(Of Double)(3, 3)
        rm(0, 0) = cosy * cosz
        rm(0, 1) = -cosx * sinz + sinx * siny * cosz
        rm(0, 2) = sinx * sinz + cosx * siny * cosz
        rm(1, 0) = cosy * sinz
        rm(1, 1) = cosx * cosz + sinx * siny * sinz
        rm(1, 2) = -sinx * cosz + cosx * siny * sinz
        rm(2, 0) = -siny
        rm(2, 1) = sinx * cosy
        rm(2, 2) = cosx * cosy
        Return mat * rm
    End Function
    Public Sub Main()

        Dim ma As Matrix(Of Double)
        Dim mb As Matrix(Of Double)

        ma = New Matrix(Of Double)(matrixA)

        ' Make second matrix by rotating X=5°, Y=6°, Z=7° and translating X+2, Y+3, Z+4
        mb = ma.Clone
        mb = Rotate(mb, New Matrix(Of Double)({radians(5), radians(6), radians(7)}))
        mb = Translate(mb, New Matrix(Of Double)({2, 3, 4}))

        Dim tx As Matrix(Of Double) = Nothing
        Dim rx As Matrix(Of Double) = Nothing
        Dim ac As Matrix(Of Double) = Nothing
        Dim bc As Matrix(Of Double) = Nothing
        Dim rotation As Matrix(Of Double) = Nothing
        Dim translation As Matrix(Of Double) = Nothing
        Dim xr As Double, yr As Double, zr As Double

        Kabsch(ma, mb, ac, bc, translation, rotation, xr, yr, zr)
        ShowMatrix("A centroid", ac)
        ShowMatrix("B centroid", bc)
        ShowMatrix("Translation", translation)
        ShowMatrix("Rotation", rotation)
        console.WriteLine(degrees(xr) & "° " & degrees(yr) & "° " & degrees(zr) & "°")

        System.Console.ReadLine()
    End Sub
    Function radians(ByVal a As Double)
        Return a * Math.PI / 180
    End Function
    Function degrees(ByVal a As Double)
        Return a * 180 / Math.PI
    End Function
    ''' <summary>
    ''' Compute translation and optimal rotation between 2 matrices using Kabsch's algorithm
    ''' </summary>
    ''' <param name="p">Starting matrix</param>
    ''' <param name="q">Rotated and translated matrix</param>
    ''' <param name="pcentroid">returned (3,1), centroid(p)</param>
    ''' <param name="qcentroid">returned (3,1), centroid(q)</param>
    ''' <param name="translation">returned (3,1), translation to get q from p</param>
    ''' <param name="rotation">returned (3,3), rotation to get q from p</param>
    ''' <param name="xr">returned, X rotation in radians</param>
    ''' <param name="yr">returned, Y rotation in radians</param>
    ''' <param name="zr">returned, Z rotation in radians</param>
    ''' <remarks>nomeclature as per http://en.wikipedia.org/wiki/Kabsch_algorithm</remarks>
    Sub Kabsch(ByVal p As Matrix(Of Double), ByVal q As Matrix(Of Double),
               ByRef pcentroid As Matrix(Of Double), ByRef qcentroid As Matrix(Of Double),
               ByRef translation As Matrix(Of Double), ByRef rotation As Matrix(Of Double),
               ByRef xr As Double, ByRef yr As Double, ByRef zr As Double)

        Dim zero As New Matrix(Of Double)({0, 0, 0})
        Dim a As Matrix(Of Double)
        Dim v As New Matrix(Of Double)(3, 3)
        Dim s As New Matrix(Of Double)(3, 3)
        Dim w As New Matrix(Of Double)(3, 3)
        Dim handed As Matrix(Of Double)
        Dim d As Double

        pcentroid = Centroid(p)
        qcentroid = Centroid(q)
        translation = qcentroid - pcentroid
        p = Translate(p, zero - pcentroid) ' move p to the origin
        q = Translate(q, zero - qcentroid) ' and q too
        a = p.Transpose * q ' 3x3 covariance
        cvSVD(a, s, v, w, SVD_TYPE.CV_SVD_DEFAULT)
        d = System.Math.Sign(a.Det)
        handed = New Matrix(Of Double)({{1, 0, 0}, {0, 1, 0}, {0, 0, 1}})
        handed.Data(2, 2) = d
        rotation = v * handed * w.Transpose ' optimal rotation matrix, U
        ' Extract X,Y,Z angles from rotation matrix
        yr = Asin(-rotation(2, 0))
        xr = Asin(rotation(2, 1) / Cos(yr))
        zr = Asin(rotation(1, 0) / Cos(yr))
    End Sub

    Function Centroid(ByVal m As Matrix(Of Double)) As Matrix(Of Double)

        Dim result As New Matrix(Of Double)(3, 1)
        Dim ui() As Double = {0, 0, 0}

        For i As Integer = 0 To m.Rows - 1
            For j As Integer = 0 To 2
                ui(j) = ui(j) + m(i, j)
            Next
        Next

        For i As Integer = 0 To 2
            result(i, 0) = ui(i) / m.Rows
        Next

        Return result

    End Function
    Sub ShowMatrix(ByVal name As String, ByVal m As Matrix(Of Double))
        console.WriteLine(name)
        For i As Integer = 0 To m.Rows - 1
            For j As Integer = 0 To m.Cols - 1
                console.Write(m(i, j) & " ")
            Next
            console.WriteLine("")
        Next
    End Sub

End Module

出力:

A centroid
0
0
0
B centroid
2
3
4
Translation
2
3
4
Rotation
0.987108879970813 -0.112363244371414 0.113976139595516
0.121201730390574 0.989879474775675 -0.0738157569097856
-0.104528463267653 0.0866782944696306 0.990737439302028
5° 6° 7°

しかし、カメラの位置を決定する方法がまだわかりません。

于 2011-09-18T17:25:53.283 に答える
1

2D または 3D 点群の 2 つのスナップショット間の差を計算するために使用する「正しい」アルゴリズムは、ICP ( Iterative Closest Point ) と呼ばれます。アルゴリズムが解決するICP

人間が読める形式: 与えられたポイント セット P1 と P2 について、P1 を P2 に変換する回転行列 R と平行移動 T を見つけます。原点を中心に正規化されていることを確認してください。

アルゴリズムは概念的に単純で、一般的にリアルタイムで使用されます。2 つの raw スキャンのポイント間の距離を最小化するために必要な変換 (平行移動、回転) を繰り返し修正します。

興味のある方は、これは計算幾何学処理内のトピックです

于 2011-09-23T10:55:18.620 に答える
0

Iterative Closest Point アルゴリズム (ICP) は、C#/VB 用の公式の Kinect SDK 1.7 の一部になりました。

VB でのカメラ ポーズの復元は非常に簡単です。

http://www.microsoft.com/en-us/kinectforwindows/develop/new.aspx

于 2013-03-29T06:29:16.220 に答える