1

2 つの異なるカメラでキャプチャされた同じシーンの 2 つの画像から抽出された 2 つの独立した特徴セット間の一致を見つける必要があります。私は HumanEvaI データ セットを使用しているので、カメラのキャリブレーション マトリックスがあります (この特定のケースでは BW1 と BW2)。

カメラが互いにかなり離れており、回転もしているため、単純な相関、SIFT、または SURF などの方法を使用して問題を解決することはできません。そのため、画像間の違いは大きく、オクルージョンもあります。

私は、すでに持っているキャリブレーション情報のために構築できたグラウンド トゥルース ポイント マッチングに基づいて、キャプチャされた画像間のホモグラフィを見つけることに集中してきました。このホモグラフィを取得したら、完全一致 (ハンガリーのアルゴリズム) を使用して、最適な対応を見つけます。ここでのホモグラフィの重要性は、点間の距離を計算する方法です。

これまでのところ、すべて問題ないようですが、私の問題は、良いホモグラフィを見つけることができなかったことです。RANSAC メソッド、サンプソン距離を使用したゴールド スタンダード メソッド (これは非線形最適化アプローチ)、および Richard Hartley による「コンピューター ビジョンの複数ビュー ジオメトリ」第 2 版と呼ばれる本から主にすべてを試しました。

これまでのところ、すべてを matlab に実装しました。

これを行う別の方法はありますか?私は正しい道にいますか?もしそうなら、私は何が間違っていたのでしょうか?

4

3 に答える 3

2

私のソリューションが興味深いと思うかもしれません。これは、コヒーレント ポイント ドリフト アルゴリズムの純粋な numpy実装です。

次に例を示します。

from functools import partial
from scipy.io import loadmat
import matplotlib.pyplot as plt
import numpy as np
import time

class RigidRegistration(object):
    def __init__(self, X, Y, R=None, t=None, s=None, sigma2=None, maxIterations=100, tolerance=0.001, w=0):
    if X.shape[1] != Y.shape[1]:
        raise 'Both point clouds must have the same number of dimensions!'

    self.X             = X
    self.Y             = Y
    (self.N, self.D)   = self.X.shape
    (self.M, _)        = self.Y.shape
    self.R             = np.eye(self.D) if R is None else R
    self.t             = np.atleast_2d(np.zeros((1, self.D))) if t is None else t
    self.s             = 1 if s is None else s
    self.sigma2        = sigma2
    self.iteration     = 0
    self.maxIterations = maxIterations
    self.tolerance     = tolerance
    self.w             = w
    self.q             = 0
    self.err           = 0

def register(self, callback):
    self.initialize()

    while self.iteration < self.maxIterations and self.err > self.tolerance:
        self.iterate()
        callback(X=self.X, Y=self.Y)

    return self.Y, self.s, self.R, self.t

def iterate(self):
    self.EStep()
    self.MStep()
    self.iteration = self.iteration + 1

def MStep(self):
    self.updateTransform()
    self.transformPointCloud()
    self.updateVariance()

def updateTransform(self):
    muX = np.divide(np.sum(np.dot(self.P, self.X), axis=0), self.Np)
    muY = np.divide(np.sum(np.dot(np.transpose(self.P), self.Y), axis=0), self.Np)

    self.XX = self.X - np.tile(muX, (self.N, 1))
    YY      = self.Y - np.tile(muY, (self.M, 1))

    self.A = np.dot(np.transpose(self.XX), np.transpose(self.P))
    self.A = np.dot(self.A, YY)

    U, _, V = np.linalg.svd(self.A, full_matrices=True)
    C = np.ones((self.D, ))
    C[self.D-1] = np.linalg.det(np.dot(U, V))

    self.R = np.dot(np.dot(U, np.diag(C)), V)

    self.YPY = np.dot(np.transpose(self.P1), np.sum(np.multiply(YY, YY), axis=1))

    self.s = np.trace(np.dot(np.transpose(self.A), self.R)) / self.YPY

    self.t = np.transpose(muX) - self.s * np.dot(self.R, np.transpose(muY))

def transformPointCloud(self, Y=None):
    if not Y:
        self.Y = self.s * np.dot(self.Y, np.transpose(self.R)) + np.tile(np.transpose(self.t), (self.M, 1))
        return
    else:
        return self.s * np.dot(Y, np.transpose(self.R)) + np.tile(np.transpose(self.t), (self.M, 1))

def updateVariance(self):
    qprev = self.q

    trAR     = np.trace(np.dot(self.A, np.transpose(self.R)))
    xPx      = np.dot(np.transpose(self.Pt1), np.sum(np.multiply(self.XX, self.XX), axis =1))
    self.q   = (xPx - 2 * self.s * trAR + self.s * self.s * self.YPY) / (2 * self.sigma2) + self.D * self.Np/2 * np.log(self.sigma2)
    self.err = np.abs(self.q - qprev)

    self.sigma2 = (xPx - self.s * trAR) / (self.Np * self.D)

    if self.sigma2 <= 0:
        self.sigma2 = self.tolerance / 10

def initialize(self):
    self.Y = self.s * np.dot(self.Y, np.transpose(self.R)) + np.repeat(self.t, self.M, axis=0)
    if not self.sigma2:
        XX = np.reshape(self.X, (1, self.N, self.D))
        YY = np.reshape(self.Y, (self.M, 1, self.D))
        XX = np.tile(XX, (self.M, 1, 1))
        YY = np.tile(YY, (1, self.N, 1))
        diff = XX - YY
        err  = np.multiply(diff, diff)
        self.sigma2 = np.sum(err) / (self.D * self.M * self.N)

    self.err  = self.tolerance + 1
    self.q    = -self.err - self.N * self.D/2 * np.log(self.sigma2)

def EStep(self):
    P = np.zeros((self.M, self.N))

    for i in range(0, self.M):
        diff     = self.X - np.tile(self.Y[i, :], (self.N, 1))
        diff    = np.multiply(diff, diff)
        P[i, :] = P[i, :] + np.sum(diff, axis=1)

    c = (2 * np.pi * self.sigma2) ** (self.D / 2)
    c = c * self.w / (1 - self.w)
    c = c * self.M / self.N

    P = np.exp(-P / (2 * self.sigma2))
    den = np.sum(P, axis=0)
    den = np.tile(den, (self.M, 1))
    den[den==0] = np.finfo(float).eps

    self.P   = np.divide(P, den)
    self.Pt1 = np.sum(self.P, axis=0)
    self.P1  = np.sum(self.P, axis=1)
    self.Np = np.sum(self.P1)

def visualize(X, Y, ax):
    plt.cla()
    ax.scatter(X[:,0] ,  X[:,1], color='red')
    ax.scatter(Y[:,0] ,  Y[:,1], color='blue')
    plt.draw()
    plt.pause(0.001)

def main():
    fish = loadmat('./data/fish.mat')
    X = fish['X'] # number-of-points x number-of-dimensions array of fixed points
    Y = fish['Y'] # number-of-points x number-of-dimensions array of moving points

    fig = plt.figure()
    fig.add_axes([0, 0, 1, 1])
    callback = partial(visualize, ax=fig.axes[0])

    reg = RigidRegistration(X, Y)
    reg.register(callback)
    plt.show()

if __name__ == '__main__':
main()
于 2016-10-31T21:53:00.453 に答える
2

次の 2 つの方法を試すことができます。

  1. 非剛体レジストレーション用の新しいポイント マッチング アルゴリズム (薄板スプラインを使用) - 比較的低速。
  2. ポイント セット登録: コヒーレント ポイント ドリフト (より速く、より正確に感じます)。

2番目の方法に関する限り、外れ値が存在する場合でも非常に優れた登録結果が得られ、高速で複雑な変換を回復できると感じています。しかし、最初の方法は、登録分野でよく知られている方法でもあり、それを試すこともできます。

アルゴリズムの核心を理解してから、オンラインで入手できるコードに進みましょう。

  1. 薄板スプラインはこちら- TPS-RPM デモをダウンロードしてください。
  2. ポイントセット登録:コヒーレントポイントドリフトはこちら
于 2013-02-11T04:47:54.980 に答える
0

役立つと思われる別の方法については、こちらで説明しています。
このアプローチは、ローカル モデルを点のグループに適合させようとします。そのグローバルな最適化方法により、いくつかの異なるローカル モデルが存在する場合、RANSAC よりも優れたパフォーマンスを発揮できます。
また、利用可能なコードがあると思います。

于 2013-02-11T07:38:09.487 に答える