У меня есть большое изображение в форме массива numpy (opencv возвращает его как 2d-массив из 3 значений uint8) и хочет вычислить сумму гауссовых ядер для каждого пикселя, то есть (в LaTeX поддержка по-прежнему отсутствует SO есть?): Вычисление функции эффективной плотности
для N различных ядер с заданной массой w, средней и диагональной ковариационной матрицей.
Так что я хочу функцию compute_densities(image, kernels) -> numpy array of floats
. Каков наилучший способ сделать это эффективно в python? Я был бы удивлен, если бы не было библиотечной функции в scipy для этого, но у меня была статистика в uni давным-давно, поэтому я немного запутался в деталях документации.
В принципе Я хочу следующее, просто более эффективное, чем наивный питон (2pi^{- 3/2} игнорируется, поскольку это постоянный фактор, который не имеет для меня значения, поскольку меня интересуют только отношения между вероятностями)
def compute_probabilities(img, kernels):
np.seterr(divide='ignore') # 1/covariance logs an error otherwise
result = np.zeros((img.shape[0], img.shape[1]))
for row_pos, row_val in enumerate(img):
for col_pos, val in enumerate(row_val):
prob = 0.0
for kernel in kernels:
mean, covariance, weight = kernel
val_sub_mu = np.array([val]).T - mean
cov_inv = np.where(covariance != 0, 1/covariance, 0)
tmp = val_sub_mu.T.dot(cov_inv).dot(val_sub_mu)
prob += weight/np.sqrt(np.linalg.norm(covariance)) * \
math.exp(-0.5 * tmp)
result[row_pos][col_pos] = prob
np.seterr(divide='warn')
return result
Вход: cv2.imread
на некоторый jpg, который дает 2d массив (высота x ширина) структуры 3 uint8, содержащей 3 цветовых канала.
Ядра является namedtuple('Kernel', 'mean covariance weight')
, значит, вектор, ковариация является 3x3
матрица со всем, но диагональ равна нулю и вес поплавка 0 < weight < 1
. Для простоты я только указать диагонали, а затем преобразовать его в матрицу 3х3 впоследствии: (представление не высечены на камне не все равно, как это представлено так быть свободным, чтобы изменить все, что):
some_kernels = [
Kernel(np.array([(73.53, 29.94, 17.76)]), np.array([(765.40, 121.44, 112.80)]), 0.0294),
...
]
def fixup_kernels(kernels):
new_kernels = []
for kernel in kernels:
cov = np.zeros((3, 3))
for pos, c in enumerate(kernel.covariance[0]):
cov[pos][pos] = c
new_kernels.append(Kernel(kernel.mean.T, cov, kernel.weight))
return new_kernels
some_kernels = fixup_kernels(some_kernels)
img = cv2.imread("something.jpg")
result = compute_probabalities(img, some_kernels)
Проверьте scipy.ndimage (http://docs.scipy.org/doc/scipy/reference/ndimage.html). Постройте свои ядра, а затем сверните их с помощью массива с помощью метода convolve. – dabillox
Добавил щедрость в надежде, что кто-то захочет представить пример того, как именно я буду использовать convolve и co для реализации этой функции. – Voo
Voo, не могли бы вы добавить в свой пример некоторые примеры значений и образец вызова compute_probabilities()? (и что он производит), я сделаю это, но не совсем очевидно, каковы типы входов. Я думаю, что ковариация - это массив KxK, где K - img.shape [2], это правильно? –