Как заменить scipy.spatial.distance на np.linalg.norm в Python - PullRequest
0 голосов
/ 02 апреля 2020

Я следую этому руководству, чтобы реализовать отслеживание объектов для моего проекта - https://www.pyimagesearch.com/2018/07/23/simple-object-tracking-with-opencv/

Метод состоит в том, чтобы найти центроиды обнаруженных объектов в начальном кадре, а затем рассчитать кратчайшее расстояние другим центроидам обнаруженных объектов, которые появляются на следующем кадре. Предполагается, что ближайший центроид был бы тем же объектом.

В учебнике -

from scipy.spatial import distance as dist
...
D = dist.cdist(np.array(objectCentroids), newCentroids)

используется для вычисления расстояния (евклидово расстояние). К сожалению, я не могу использовать модуль scipy, так как пытаюсь развернуть его на AWS Lambda (ограничение размера). В этом случае рекомендуется использовать это - https://docs.scipy.org/doc/numpy/reference/generated/numpy.linalg.norm.html

D = np.linalg.norm(objectCentroids – newCentroids)

Проблема заключается в том, что, в отличие от dist.cdist, где он вычисляет все и любую матрицу, np.linalg.norm выводит только 1 значение, которое рассчитывается после вычитания newCentroids из матрицы objectCentroids. Я собираюсь l oop более чем в n раз (как бы ни была велика матрица) и добавляю к другой матрице, чтобы получить нужный мне результат. Однако я не был уверен, правильно ли я понимаю эту концепцию или нет, поэтому я хотел обратиться за помощью. Если кто-нибудь знает лучший способ, я был бы признателен за любой указатель.

ОБНОВЛЕНИЕ

На основании полученных отзывов / ответов я немного обновил код и хорошо ... кажется, что работает -

n = arrayObjectCentroids.shape[0]
m = inputCentroids.shape[0]

T = []

for i in range(0,n):
    for z in range(0,m):
        Tv = np.linalg.norm(arrayObjectCentroids[i] - inputCentroids[z])
        # print(f'Tv is \n {Tv}')
        T = np.append(T, Tv)
        # print(f'T is \n {T}')
    print(f'new T is \n {T}')   
D = np.reshape(T, (n, m))
print(f'D is \n {D}')

В этом случае, если есть один объект и немного двигается -

newCentroids равен [[224 86]], и форма его is (1, 2) ... objectCentroids равен [[224 86]], а форма objectCentroids равна (1, 2)

D равно [[0.]]

Если у меня 3 объекта, -

новые центроиды имеют

 [[228  79]
 [ 45 127]
 [103 123]]

форма вводаCentroids равна (3, 2)

objectCentroids равна

 [[228  79]
 [ 45 127]
 [103 123]]

форма объектаCentroids равна (3, 2 )

D - это

 [[  0.         189.19038031 132.51792332]
 [189.19038031   0.          58.13776741]
 [132.51792332  58.13776741   0.        ]]

Здорово, что это работает, но я чувствую, что это может быть не лучшим решением, и если у вас есть указатель, я был бы признателен! Спасибо!

Ответы [ 2 ]

0 голосов
/ 02 апреля 2020

РЕДАКТИРОВАТЬ: Отредактированный код для адреса комментариев ниже

Если в вашем случае у вас есть векторы в евклидовом пространстве, то np.linalg.norm вернет длину этого вектора.

Итак, objectCentroid – newCentroid даст вам вектор между точкой в ​​objectCentroid и точкой в ​​newCentroid. Обратите внимание, что это между 2 точками, а не массивом, содержащим ВСЕ точки.

Чтобы получить все комбинации точек, я использовал itertools, а затем изменил массив, чтобы получить тот же результат, что и dist

import numpy as np
from scipy.spatial import distance as dist
import itertools

# Example data
objectCentroids = np.array([[0,0,0],[1,1,1],[2,2,2], [3,3,3]])
newCentroids    = np.array([[4,4,4],[5,5,5],[6,6,6],[7,7,7]])
comb            = list(itertools.product(objectCentroids, newCentroids))
all_dist        = [] 

for pair in comb:

    dis = np.linalg.norm((pair[0] - pair[1]))
    all_dist.append(dis)

all_dist = np.reshape(all_dist, (len(objectCentroids), len(objectCentroids)))
D        = dist.cdist(objectCentroids, newCentroids)   

print(D)
print(" ")
print(all_dist)
0 голосов
/ 02 апреля 2020

Вы можете использовать Numpy трансляцию для создания матрицы расстояний.

Подробнее об этом здесь и здесь .

Основа c идея такова:

Сложите (измените форму) ваши центроиды как (1, n, 3) и (n, 1, 3), где последнее измерение с формой 3 будет (x,y,z). Затем вычтите массивы и используйте np.linalg.norm, чтобы вычислить расстояние вдоль оси ... хм ... вероятно, последнее. Это должно дать квадратную (n,n) матрицу расстояний.

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