Я пытаюсь применить сдвиговое преобразование к простому двумерному линейному фильтру (представленному в виде двоичного изображения), используя методы интерполяции в 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 является интерпретируемым языком программирования.
Ваш сдвиг работает в направлении, отличном от того, чего вы ожидаете.
Попробуйте поместить строку в массив фильтров как
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
— вторая, поскольку матрица представлена как массив строк (и мы выбираем строку по первому индексу, а затем позицию в строке по второй индекс).