リスト内包表記は、numpy 配列を扱うには非常に非効率的な方法です。それらは、距離の計算には特に適していません。
データとポイントの違いを見つけるには、単にdata - point
. 次に、 を使用して距離を計算するnp.hypot
か、必要に応じて、距離を 2 乗して合計し、平方根をとります。
ただし、計算の目的で Nx2 配列にすると、少し簡単になります。
基本的に、次のようなものが必要です。
import numpy as np
data = np.array([[[1704, 1240],
[1745, 1244],
[1972, 1290],
[2129, 1395],
[1989, 1332]],
[[1712, 1246],
[1750, 1246],
[1964, 1286],
[2138, 1399],
[1989, 1333]],
[[1721, 1249],
[1756, 1249],
[1955, 1283],
[2145, 1399],
[1990, 1333]]])
point = [1989, 1332]
#-- Calculate distance ------------
# The reshape is to make it a single, Nx2 array to make calling `hypot` easier
dist = data.reshape((-1,2)) - point
dist = np.hypot(*dist.T)
# We can then reshape it back to AxBx1 array, similar to the original shape
dist = dist.reshape(data.shape[0], data.shape[1], 1)
print dist
これにより、次の結果が得られます。
array([[[ 299.48121811],
[ 259.38388539],
[ 45.31004304],
[ 153.5219854 ],
[ 0. ]],
[[ 290.04310025],
[ 254.0019685 ],
[ 52.35456045],
[ 163.37074401],
[ 1. ]],
[[ 280.55837182],
[ 247.34186868],
[ 59.6405902 ],
[ 169.77926846],
[ 1.41421356]]])
現在、最も近い要素を削除することは、単に最も近い要素を取得するよりも少し困難です。
numpy では、ブール値のインデックス付けを使用して、これをかなり簡単に行うことができます。
ただし、軸の配置について少し心配する必要があります。
重要なのは、numpy が最後の軸に沿って操作を「ブロードキャスト」することを理解することです。この場合、中央の軸に沿ってブロードキャストしたいと考えています。
また、-1
軸のサイズのプレースホルダーとしても使用できます。Numpy は-1
、軸のサイズとして を入れると許容サイズを計算します。
私たちがしなければならないことは、次のようになります。
#-- Remove closest point ---------------------
mask = np.squeeze(dist) != dist.min(axis=1)
filtered = data[mask]
# Once again, let's reshape things back to the original shape...
filtered = filtered.reshape(data.shape[0], -1, data.shape[2])
1 行にすることもできますが、読みやすくするために分割しています。重要なのはdist != something
、元の配列にインデックスを付けるために使用できるブール配列を生成することです。
だから、それをすべてまとめる:
import numpy as np
data = np.array([[[1704, 1240],
[1745, 1244],
[1972, 1290],
[2129, 1395],
[1989, 1332]],
[[1712, 1246],
[1750, 1246],
[1964, 1286],
[2138, 1399],
[1989, 1333]],
[[1721, 1249],
[1756, 1249],
[1955, 1283],
[2145, 1399],
[1990, 1333]]])
point = [1989, 1332]
#-- Calculate distance ------------
# The reshape is to make it a single, Nx2 array to make calling `hypot` easier
dist = data.reshape((-1,2)) - point
dist = np.hypot(*dist.T)
# We can then reshape it back to AxBx1 array, similar to the original shape
dist = dist.reshape(data.shape[0], data.shape[1], 1)
#-- Remove closest point ---------------------
mask = np.squeeze(dist) != dist.min(axis=1)
filtered = data[mask]
# Once again, let's reshape things back to the original shape...
filtered = filtered.reshape(data.shape[0], -1, data.shape[2])
print filtered
収量:
array([[[1704, 1240],
[1745, 1244],
[1972, 1290],
[2129, 1395]],
[[1712, 1246],
[1750, 1246],
[1964, 1286],
[2138, 1399]],
[[1721, 1249],
[1756, 1249],
[1955, 1283],
[2145, 1399]]])
余談ですが、複数のポイントが等しく近い場合、これは機能しません。Numpy 配列は各次元に沿って同じ数の要素を持つ必要があるため、その場合はグループ化をやり直す必要があります。