7

背景/コンテキスト

scipyndimage.affine_transform関数によって出力された値を再現しようとしていましたが、scipy実装とは異なる「3 次」補間スキームを使用しているようです。

非常に単純な例を見てみましょう (3 次補間を使用したいデータではありませんが、理解しやすいものです)。値を確認するために、一様な Catmull-Rom splinesを実装しました。私の小さな実装例:

import numpy as np
from scipy.ndimage import affine_transform


def catmull_rom_interp(p0, p1, p2, p3, x):
    return (
        (-0.5 * p0 + 1.5 * p1 - 1.5 * p2 + 0.5 * p3) * (x ** 3)
        + (p0 - 2.5 * p1 + 2 * p2 - 0.5 * p3) * (x ** 2)
        + (-0.5 * p0 + 0.5 * p2) * x
        + p1
    )


image = np.zeros((9,))
image[3] = 13.3

scipy_result_filtered = affine_transform(
    image, np.eye(1), offset=-1.7, order=3, prefilter=True
)
scipy_result = affine_transform(image, np.eye(1), offset=-1.7, order=3, prefilter=False)

image_padded = np.pad(image, 3, mode="constant", constant_values=0)
result_manual = np.zeros((9,))

for i in range(9):
    result_manual[i] = catmull_rom_interp(*image_padded[i : i + 4], 0.3)

print(scipy_result)
print(scipy_result_filtered)
print(result_manual)

# yields
# [0. 0. 0.          0.05985    4.63061667  7.84921667  0.76031667 0.          0.        ]
# [0. 0. 0.1675183  -1.06094923 4.43537861 11.10313479 -1.75261778 0.46923634 -0.12432758]
# [0. 0. 0.         -0.41895    3.85035    10.84615    -0.97755    0.          0.        ]


#
#    PLOTTING
#

import matplotlib.pyplot as plt

plt.gca().grid()

plots = []
for i in range(9):
    plots.append(lambda x: catmull_rom_interp(*image_padded[i : i + 4], x))

plt.plot(scipy_result, "--", label="scipy", alpha=0.5)
plt.plot(scipy_result, "o", color=plt.get_cmap("tab10")(0))

plt.plot(scipy_result_filtered, "--", label="scipy filtered", alpha=0.5)
plt.plot(scipy_result_filtered, "o", color=plt.get_cmap("tab10")(1))
plt.plot(result_manual, "o")
for i in range(9):
    plt.plot(
        np.linspace(i - 0.3, i + 1 - 0.3, 100),
        plots[i](np.linspace(0, 1, 100)),
        "--",
        alpha=0.5,
        color=plt.get_cmap("tab10")(2),
        label="Catmull-Rom spline" if i == 0 else None,
    )

plt.plot(
    np.arange(-0.3, 8.8),
    [0] * 2 + list(image[:-1]),
    "o",
    label="Data to interpolate",
    color="k",
)


plt.legend(framealpha=1)
plt.show()

次のプロットが得られます(scipy関数の真の補間関数がわからないため、さまざまなデータポイントをより強調するために線形接続をプロットしただけであることに注意してください): ここに画像の説明を入力

所見:

  • scipy メソッドは Catmull-Rom スプラインを使用しません
  • scipy メソッド (フィルタリングなし) は、通常、鋭いエッジの 3 次補間に関連するオーバーシュートを生成しませんが、scipy のドキュメントに記載されているように、多少のぼやけが発生します。また、これは、私が使用した画像の特定のシフトに関連しているようです例
  • 事前にフィルター処理された scipy メソッドは、Catmull-Rom スプラインに近いですが、同一ではありません (目に見える違いがあります)。

質問

  • scipy はどの補間スキームを使用しますか?
  • ドキュメントやコードのどこで実際に見つけることができますか?
  • ボーナス:Pythonで(チェック目的で)実装する簡単な方法
4

1 に答える 1

1

まだコメントできないので、関数のソース コードはhttps://github.com/scipy/scipy/blob/master/scipy/ndimage/interpolation.py#L355にあります。

基本的な変換/エラーチェックを行ってから、パラメータに応じてzoomShiftまたはgeometryTransform にフィードするようです。

残念ながら、私は 1 つまたは 3 つ以上に答えるだけの十分な洞察を持っていません。

于 2019-07-31T20:53:54.047 に答える