Как рассчитать ось ориентации? - PullRequest
8 голосов
/ 03 мая 2011

Ранее я вычислял ось ориентации на основе анатомических структур, таких как пальцы на лапах.

enter image description here

Но я обнаружил, что это не работает, когда яне может отличить пальцы очень хорошо или если пятка (синий квадрат) далеко.Поэтому я решил поискать лучшие альтернативы и попытался вычислить инерциальную ось .

Эта страница дает отличное объяснение того, как его вычислить , но у меня возникают проблемы с пониманием шагов по переходу от центра масс (или давления в моем случае) к углу.

enter image description here

Объяснение сводится к следующему: enter image description here, который использует центр давления и значение p, из которого я не знаю, что это такое.

У меня был доступ к коду Matlab, который вычислял эту ось для человеческих ног, и сделал все возможное, чтобы перевести ее на Python:

x = 0.508 # sensor size in the x-direction
y = 0.762 # sensor size in the y-direction
Ptot = 0 # total pressure 
Px   = 0 # first order moment(x)
Py   = 0 # first order moment(y)
Pxx  = 0 # second order moment (y)
Pyy  = 0 # second order moment (x)
Pxy  = 0 # second order moment (xy)

for row in range(rows): # y-direction
    for col in range(cols): # x-direction
        if data[row,col] > 0.0: # If not zero
            temp = 1
        else:
            temp = 0
        Ptot = Ptot + temp # Add 1 for every sensor that is nonzero
        Px = Px   + (x * col + x / 2) * temp
        Py = Py   + (y * row + y / 2) * temp
        Pxx = Pxx + (x * y * y * y / 12 + x * y * (row * y + y / 2) * (row * y + y / 2) ) * temp
        Pyy = Pyy + (y * x * x * x / 12 + x * y * (col * x + x / 2) * (col * x + x / 2) ) * temp        
        Pxy = Pxy + (x * y * (row * y + y / 2) * (row * x + x / 2)) * temp

CoPY = Py / Ptot
CoPX = Px / Ptot
CoP = [CoPX, CoPY]

Ixx = Pxx - Ptot * self.x * self.y * CoPY * CoPY
Iyy = Pyy - Ptot * self.x * self.y * CoPX * CoPX
Ixy = Pxy - Ptot * self.x * self.y * CoPY * CoPX
angle = (math.atan(2 * Ixy / (Iyy - Ixx))) / 2

Ixp = Ixx * math.cos(angle) * math.cos(angle) + Iyy * math.sin(angle) * math.sin(angle) - 2 * Ixy * math.sin(angle) * math.cos(angle)
Iyp = Iyy * math.cos(angle) * math.cos(angle) + Ixx * math.sin(angle) * math.sin(angle) + 2 * Ixy * math.sin(angle) * math.cos(angle)
RotationMatrix = [[math.cos(angle), math.sin(angle)], [-math.sin(angle), math.cos(angle)]]

Итак, насколько я понял, sin (angle) и cos (угол) от RotationMatrix используются для определения оси.Но я не совсем понимаю, как использовать эти значения, чтобы нарисовать ось через лапу и вращать ее вокруг нее .

Любая идея, что я делаю неправильно и /или что я должен сделать, чтобы решить это?

Если кто-то чувствует необходимость в эксперименте, вот файл с всеми нарезанными массивами, которые содержат данные о давлении каждой лапы .Для пояснения: walk_sliced_data - это словарь, который содержит ['ser_3', 'ser_2', 'sel_1', 'sel_2', 'ser_1', 'sel_3'], которые являются названиями измерений.Каждое измерение содержит другой словарь, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] (пример из «sel_1»), который представляет воздействия, которые были извлечены.

1 Ответ

8 голосов
/ 03 мая 2011

Ну, вот реализация, которая делает то же самое, что и ваш код выше (и поворачивает изображение на соответствующий угол).

Однако в случае ваших лап я не уверен, чтоработать так же, как и для человеческой ноги.

Прежде всего, для лапы собаки «длинная» ось, определенная таким образом, расположена вдоль ширины лапы, а не по длине лапы.Это не имеет большого значения, если оно согласованно, поскольку мы можем просто повернуть на угол, рассчитанный вместо 90 - угол, вычисленный.

Однако тот факт, что лапа собаки близка к круглой, вызывает у нас больше проблем.

В принципе, это, вероятно, не будет так полезно для собак, как для людей.Вращение «длинной» оси, определяемое ковариационной матрицей изображения, сформированного из вторых центральных моментов изображения (что и делает (я думаю) ваш код выше), с меньшей вероятностью будет точным измерением ориентациилапа

Другими словами, лапа собаки близка к круглой, и они, кажется, кладут большую часть своего веса на пальцы ног, поэтому «задний» палец ноги весит меньше, чем шрифт в этом расчете.Из-за этого ось, которую мы получаем, не будет постоянно иметь отношение к положению «заднего» пальца и передних пальцев.(Надеюсь, в этом был какой-то смысл ... Я ужасный писатель ... Вот почему я отвечаю на этот вопрос, а не работаю над бумагой, над которой мне следует работать ...)

В любом случаескорость, достаточная скорость ... Вот пример:

import cPickle
import numpy as np
import matplotlib.pyplot as plt

from scipy import ndimage

def main():
    measurements = cPickle.load(open('walk_sliced_data', 'r'))
    plot(measurements['ser_1'].values())
    plt.show()

def raw_moment(data, iord, jord):
    nrows, ncols = data.shape
    y, x = np.mgrid[:nrows, :ncols]
    data = data * x**iord * y**jord
    return data.sum()

def intertial_axis(data):
    data_sum = data.sum()
    m10 = raw_moment(data, 1, 0)
    m01 = raw_moment(data, 0, 1)
    x_bar = m10 / data_sum
    y_bar = m01 / data_sum
    u11 = (raw_moment(data, 1, 1) - x_bar * m01) / data_sum
    u20 = (raw_moment(data, 2, 0) - x_bar * m10) / data_sum
    u02 = (raw_moment(data, 0, 2) - y_bar * m01) / data_sum
    angle = 0.5 * np.arctan(2 * u11 / (u20 - u02))
    return x_bar, y_bar, angle


def plot(impacts):
    def plot_subplot(pawprint, ax):
        x_bar, y_bar, angle = intertial_axis(pawprint)
        ax.imshow(pawprint)
        plot_bars(x_bar, y_bar, angle, ax)
        return angle

    fig1 = plt.figure()
    fig2 = plt.figure()
    for i, impact in enumerate(impacts[:9]):
        ax1 = fig1.add_subplot(3,3,i+1)
        ax2 = fig2.add_subplot(3,3,i+1)

        pawprint = impact.sum(axis=2)
        angle = plot_subplot(pawprint, ax1)

        pawprint = ndimage.rotate(pawprint, np.degrees(angle))
        plot_subplot(pawprint, ax2)

    fig1.suptitle('Original')
    fig2.suptitle('Rotated')

def plot_bars(x_bar, y_bar, angle, ax):
    def plot_bar(r, x_bar, y_bar, angle, ax, pattern):
        dx = r * np.cos(angle)
        dy = r * np.sin(angle)
        ax.plot([x_bar - dx, x_bar, x_bar + dx], 
                [y_bar - dy, y_bar, y_bar + dy], pattern)
    plot_bar(1, x_bar, y_bar, angle + np.radians(90), ax, 'wo-')
    plot_bar(3, x_bar, y_bar, angle, ax, 'ro-')
    ax.axis('image')


if __name__ == '__main__':
    main()

На этих графиках центральная точка является центром тяжести изображения, а красная линия определяет «длинную» ось, а белая линия определяет«короткая» ось.

Оригинальные (не повернутые) лапы: enter image description here

Повернутые лапы: enter image description here

Одна вещь, на которую следует обратить внимание ... Япросто вращая изображение вокруг его центра.(Кроме того, scipy.ndimage.rotate работает так же хорошо для массивов ND, как и для 2D. Вы также можете легко повернуть исходный 3D-массив "pawprint-over-time".)

Если вы хотите повернуть егоо точке (скажем, центроиде), и переместите эту точку в новую позицию на новом изображении, вы можете сделать это довольно легко в модуле ndimage Сципи с помощью нескольких трюков.Я могу привести пример, если хотите.Это немного длинно для этого примера, хотя ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...