Как правильно срезать линию в 2D-изображении с помощью интерполяции в Python?

Я пытаюсь применить сдвиговое преобразование к простому двумерному линейному фильтру (представленному в виде двоичного изображения), используя методы интерполяции в Python. Однако полученное изображение после применения преобразования сдвига выглядит почти идентично входному фильтру, без видимого эффекта сдвига.

Когда я применяю то же преобразование сдвига к функции Гаусса (еще одно 2D-изображение), сдвиг работает так, как ожидалось.

Вот код, который я использую для применения сдвига:

[![import numpy as np
import matplotlib.pyplot as plt
from scipy import interpolate, ndimage

# Define the original 2D function f(x, y)
def f(x, y, sigma, muu):
    dst = np.sqrt(x ** 2 + y ** 2)
    normal = 1 / (2.0 * np.pi * sigma ** 2)
    gauss = np.exp(-((dst - muu) ** 2 / (2.0 * sigma ** 2))) * normal
    return gauss

# Dimensions
x_dim, y_dim = 5, 19
x_values = np.linspace(-(x_dim // 2), (x_dim // 2), x_dim)
y_values = np.linspace(-(y_dim // 2), (y_dim // 2), y_dim)
xv, yv = np.meshgrid(x_values, y_values, indexing='ij')

# Shearing parameters
a = 2
b = 1
interp_method = "linear"

# Generate image A and sheared version A_ab
A = f(xv, yv, 2, 0)
A_ab = f(xv * a + yv * b, yv, 2, 0)

# Create a line filter
filter = np.zeros((x_dim, y_dim))
filter\[:, y_dim // 2\] = 1

# Interpolation of A and the filter
interp_A = interpolate.RegularGridInterpolator(
    (x_values, y_values), A, bounds_error=False, fill_value=None, method=interp_method)
interp_filter = interpolate.RegularGridInterpolator(
    (x_values, y_values), filter, bounds_error=False, fill_value=None, method=interp_method)

# Shearing transformation
out_xv = xv * a + yv * b
out_yv = yv
sheared_coords_EPI = np.transpose(np.array((out_xv, out_yv)), axes=(1, 2, 0))
sheared_A = interp_A(sheared_coords_EPI)
sheared_filter = interp_filter(sheared_coords_EPI)

# Shift coordinates to positive space for warping
x_shift = x_dim // 2
y_shift = y_dim // 2
shifted_out_xv = out_xv + x_shift
shifted_out_yv = out_yv + y_shift

# Warp the filter using the new coordinates
sheared_filter2 = ndimage.map_coordinates(filter, \[shifted_out_xv, shifted_out_yv\], order=1, mode='constant', cval=0.0)

# Flatten and interpolate the filter
points = np.vstack((xv.flatten(), yv.flatten())).T
values = filter.flatten()
new_points = np.vstack((out_xv.flatten(), out_yv.flatten())).T
interpolated_filter = interpolate.griddata(points, values, new_points, method='linear')
interpolated_filter = interpolated_filter.reshape((x_dim, y_dim))

# Plotting
plt.figure(), plt.imshow(A), plt.title("A")
plt.figure(), plt.imshow(A_ab), plt.title("A_ab")
plt.figure(), plt.imshow(sheared_A), plt.title("sheared_A")
plt.figure(), plt.imshow(filter), plt.title("filter")
plt.figure(), plt.imshow(sheared_filter), plt.title("sheared_filter")
plt.figure(), plt.imshow(sheared_filter2), plt.title("sheared_filter2")
plt.figure(), plt.imshow(interpolated_filter), plt.title("interpolated_filter")
plt.show()]

🤔 А знаете ли вы, что...
Python является интерпретируемым языком программирования.


51
1

Ответ:

Решено

Ваш сдвиг работает в направлении, отличном от того, чего вы ожидаете.

Попробуйте поместить строку в массив фильтров как filter[x_dim // 2, :] = 1 и вы увидите, что все работает нормально.

Но вертикальная линия 0 останется нетронутой, а 0 находится точно в центре вашего изображения.

Гауссиан имеет круговую симметрию, поэтому преобразование сдвига изменит его одинаково в горизонтальном и вертикальном направлениях.

Вероятно, основная проблема вашего кода в том, что вы используете x везде, где он должен быть y, и наоборот.

Т.е. когда вы создаете фильтр, вы вызываете np.zeros((x_dim, y_dim)), где x_dim=5 и y_dim=19, но если вы посмотрите на картинку или на сам массив, то увидите, что его высота равна 5, а ширина 19 — оси перепутаны.

В numpy (и в области линейной алгебры в целом) y — это первая координата, а x — вторая, поскольку матрица представлена ​​как массив строк (и мы выбираем строку по первому индексу, а затем позицию в строке по второй индекс).