Так что, если я правильно понимаю вашу формулу и код, у вас есть одно (двоичное) изображение B
и (основная истина) изображение G
. «Точки» определяются позициями пикселей, где любое изображение имеет значение True
(или, по крайней мере, ненулевое). Из вашего bitwise_xor
я делаю вывод, что оба изображения имеют одинаковую форму (M,N)
.
Таким образом, величина d^2(b,g)
в худшем случае представляет собой массив размером (M*N, M*N)
, связывающий каждый пиксель B
с каждым пикселем G
. Еще лучше: нам нужна форма (m,n)
, только если в B
ненулевые m
и G
ненулевые n
. Если ваши изображения не являются огромными, мы можем избежать отслеживания этого большого количества. Это будет стоить памяти, но мы выиграем много процессорного времени за счет векторизации. Таким образом, нам нужно только найти минимум этого расстояния по отношению к каждому n
возможному значению для каждого m
. Тогда просто суммируйте каждый минимум. Обратите внимание, что приведенное ниже решение использует крайнюю векторизацию, и оно может легко поглотить вашу память, если изображения большие.
Предполагая расстояние до Манхэттена (с квадратом в d^2
, который, кажется, отсутствует в вашем коде):
import numpy as np
# generate dummy data
M,N = 100,100
B = np.random.rand(M,N) > 0.5
G = np.random.rand(M,N) > 0.5
def MSD(B, G):
# get indices of nonzero pixels
nnz_B = B.nonzero() # (x_inds, y_inds) tuple, x_inds and y_inds are shape (m,)
nnz_G = G.nonzero() # (x_inds', y_inds') each with shape (n,)
# np.array(nnz_B) has shape (2,m)
# compute squared Manhattan distance
dist2 = abs(np.array(nnz_B)[...,None] - np.array(nnz_G)[:,None,:]).sum(axis=0)**2 # shape (m,n)
# alternatively: Euclidean for comparison:
#dist2 = ((np.array(nnz_B)[...,None] - np.array(nnz_G)[:,None,:])**2).sum(axis=0)
mindist2 = dist2.min(axis=-1) # shape (m,) of minimum square distances
return mindist2.mean() # sum divided by m, i.e. the MSD itself
print(MSD(B, G))
Если приведенное выше использует слишком много памяти, мы можем ввести цикл над элементами nnz_B
и векторизовать только элементы nnz_G
. Это займет больше мощности процессора и меньше памяти. Этот компромисс типичен для векторизации.