Функция affine_grid
Функция affine_grid генерирует двумерную координатную сетку на основе матрицы аффинного преобразования. Она принимает матрицу трансформации размером (N, 2, 3) для 2D или (N, 3, 4) для 3D, а также целевой размер выходной сетки. Сгенерированная сетка используется в функции grid_sample для применения преобразования к входному тензору.
Параметр theta задаёт матрицу аффинного преобразования в однородных координатах. Параметр size определяет выходной размер сетки, который должен соответствовать размеру входного тензора для grid_sample. Флаг align_corners управляет выравниванием пикселей по углам, обеспечивая совместимость с различными библиотеками обработки изображений.
Синтаксис
torch.nn.functional.affine_grid(theta, size, align_corners=False)
Параметры
theta (Tensor): Матрица аффинного преобразования размером (N, 2, 3) для 2D или (N, 3, 4) для 3D
size (torch.Size): Выходной размер сетки, например (N, C, H, W) для 2D
align_corners (bool): Флаг выравнивания по углам, по умолчанию False
Пример
Создадим матрицу поворота на 30 градусов и сгенерируем координатную сетку:
import torch
import torch.nn.functional as F
import math
torch.manual_seed(0)
# Матрица поворота на 30 градусов
angle = math.radians(30)
rotation_matrix = torch.tensor([
[math.cos(angle), -math.sin(angle), 0],
[math.sin(angle), math.cos(angle), 0]
], dtype=torch.float)
# Добавляем размерность батча
theta = rotation_matrix.unsqueeze(0) # (1, 2, 3)
# Генерируем сетку для изображения 64x64
size = (1, 3, 64, 64)
grid = F.affine_grid(theta, size, align_corners=False)
print(grid.shape)
print(grid[0, 0, 0])
Результат выполнения кода:
torch.Size([1, 64, 64, 2])
tensor([-0.8660, -0.5000])
Пример
Создадим масштабирование и сдвиг, а затем применим преобразование с помощью grid_sample:
import torch
import torch.nn.functional as F
torch.manual_seed(0)
# Создаём тестовое изображение
image = torch.randn(1, 1, 5, 5)
# Матрица масштабирования в 2 раза и сдвига
theta = torch.tensor([
[2.0, 0.0, 0.5],
[0.0, 2.0, 0.3]
], dtype=torch.float).unsqueeze(0) # (1, 2, 3)
# Генерируем сетку
size = (1, 1, 5, 5)
grid = F.affine_grid(theta, size, align_corners=False)
# Применяем преобразование
transformed = F.grid_sample(image, grid, align_corners=False)
print("Исходное изображение:")
print(image.squeeze())
print("Преобразованное изображение:")
print(transformed.squeeze())
Результат выполнения кода:
Исходное изображение:
tensor([
[ 1.5410, -0.2934, -2.1788, 0.5684, -1.0845],
[-1.3986, 0.4033, 0.8380, -0.7193, -0.4033],
[-0.5966, 0.1820, -0.8567, 1.1006, -1.0712],
[ 0.1227, -0.5663, 0.3731, 0.5098, 1.4365],
[ 0.0120, -1.3044, -0.4594, 1.0060, -1.0228]
])
Преобразованное изображение:
tensor([
[ 0.1820, 0.1820, 0.2989, -0.3954, -0.3954],
[ 0.1820, 0.1820, 0.2989, -0.3954, -0.3954],
[ 0.3388, 0.3388, 0.4294, -0.5885, -0.5885],
[ 0.3470, 0.3470, 0.1496, -0.3712, -0.3712],
[ 0.3470, 0.3470, 0.1496, -0.3712, -0.3712]
])
Пример
Используем флаг align_corners для управления выравниванием пикселей:
import torch
import torch.nn.functional as F
torch.manual_seed(0)
# Единичная матрица (без преобразования)
theta = torch.tensor([
[1.0, 0.0, 0.0],
[0.0, 1.0, 0.0]
], dtype=torch.float).unsqueeze(0) # (1, 2, 3)
size = (1, 1, 4, 4)
# Сравниваем два режима
grid_false = F.affine_grid(theta, size, align_corners=False)
grid_true = F.affine_grid(theta, size, align_corners=True)
print("align_corners=False (первая строка):")
print(grid_false[0, 0, :])
print("align_corners=True (первая строка):")
print(grid_true[0, 0, :])
Результат выполнения кода:
align_corners=False (первая строка):
tensor([[-0.7500, -0.7500],
[-0.2500, -0.7500],
[ 0.2500, -0.7500],
[ 0.7500, -0.7500]])
align_corners=True (первая строка):
tensor([[-1.0000, -1.0000],
[-0.3333, -1.0000],
[ 0.3333, -1.0000],
[ 1.0000, -1.0000]])
Смотрите также
-
функцию
grid_sample,
которая применяет сгенерированную сетку к входному тензору -
функцию
interpolate,
которая изменяет размер изображения с использованием различных режимов интерполяции -
функцию
pad,
которая добавляет отступы к тензору -
функцию
conv2d,
которая выполняет двумерную свёртку