Геометрия
Геометрические преобразования
Цели урока
- Записывать поворот, масштабирование, отражение и сдвиг матрицами 2x2
- Использовать однородные координаты, чтобы перенос вошёл в матричное умножение
- Композировать преобразования через произведение матриц справа налево
- Различать аффинные и проективные преобразования по сохраняемым инвариантам
- Узнавать те же примитивы в GPU pipeline, NeRF, SLAM и data augmentation
Каждый кадр в Vulkan и Metal проходит через 4x4 матрицу. RTX 4090 делает порядка 100 миллионов таких умножений в секунду - и это до того как пиксель попадёт на экран. NeRF и Tesla Autopilot решают обратную задачу: восстановить 3D-сцену, обратив те же матрицы.
- **CSS/SVG transforms (W3C, 2012):** matrix(a,b,c,d,tx,ty) - аффинная 3x3 на каждом анимированном UI-компоненте
- **GPU pipeline (OpenGL/Vulkan/Metal):** model→view→projection - три 4x4 умножения на каждую вершину
- **Tesla Autopilot и ARKit:** SLAM строит карту через композицию camera extrinsics, миллионы матриц в секунду
- **torchvision.transforms.RandomAffine:** data augmentation в CV - случайные аффинные на каждом батче
- **Spatial Transformer Networks (Jaderberg, 2015):** CNN сама учится генерировать аффинную матрицу
Эрлангенская программа Феликса Клейна
В 1872 году Феликс Клейн прочитал вступительную лекцию в Эрлангенском университете и предложил единую организующую идею: геометрия - это изучение свойств, инвариантных относительно группы преобразований. Евклидова геометрия отвечает группе движений твёрдого тела. Аффинная геометрия стоит на ступень выше, отбрасывая длины и углы, но сохраняя параллельность. Проективная геометрия идёт ещё выше и сохраняет только прямолинейность. Эрлангенская программа - причина, по которой графический инженер в 2026 году по-прежнему работает с той же иерархией изометрия, подобие, аффинное, проективное, которую Клейн заложил сто пятьдесят четыре года назад.
Предварительные знания
- Координатная геометрия и векторы на плоскости
- Умножение матриц и его свойства
Основные преобразования
Каждый кадр в Vulkan и Metal проходит через 4x4 матрицу: вершина модели умножается на model, потом view, потом projection. RTX 4090 делает порядка 100 миллионов таких умножений в секунду - и это до того как пиксель попадёт на экран.
Геометрические преобразования - перенос, поворот, отражение, масштабирование - представляются умножением на матрицу. Это позволяет комбинировать их за O(1) и переносить вычисление на GPU, где параллельно умножаются миллионы вершин по одной формуле. Пайплайн model→view→projection - буквально умножение трёх матриц перемножение матриц в строгом порядке.
| Преобразование | Матрица 2x2 | Параметры |
|---|---|---|
| Масштаб | [[sx, 0], [0, sy]] | sx, sy - коэффициенты масштаба |
| Поворот на θ | [[cosθ, -sinθ], [sinθ, cosθ]] | θ - угол против часовой стрелки |
| Отражение по оси X | [[1, 0], [0, -1]] | Зеркало по горизонтали |
| Сдвиг (shear) | [[1, sh], [0, 1]] | sh - коэффициент сдвига по X |
OpenGL и Vulkan ровно эти матрицы и считают - shader-код vertex stage умножает вершину на uniform-матрицу преобразования. В CUDA-ядрах NVIDIA каждый warp обрабатывает 32 вершины параллельно по той же формуле.
Матрица поворота на 90 градусов против часовой стрелки переведёт точку (3, 0) в:
Однородные координаты
Перенос нельзя выразить умножением на матрицу 2x2: f(x) = x + t не линейно (нет f(0) = 0). Однородные координаты добавляют третью компоненту и позволяют включить перенос в матрицу - все 2D-преобразования становятся 3x3, все 3D - 4x4. Именно поэтому WebGL, ARKit и Tesla Autopilot работают с матрицами 4x4 даже для плоских задач: одна форма умножения покрывает и линейную часть, и сдвиг.
**2D однородные координаты:** точка (x, y) становится (x, y, 1) **Матрица переноса на (tx, ty):** [[1, 0, tx], [0, 1, ty], [0, 0, 1]] **Полная 2D матрица:** [[sx·cosθ, -sy·sinθ, tx], [sx·sinθ, sy·cosθ, ty], [0, 0, 1]]
CSS `transform: matrix(a,b,c,d,tx,ty)` - это ровно однородная матрица [[a,c,tx],[b,d,ty],[0,0,1]]. Каждый animated React-компонент с transform пересчитывает её на каждом кадре GPU compositor-а в Chromium и Safari.
Дополнительный бонус: однородные координаты дают язык для проективной геометрии. Точки на бесконечности получают вид (x, y, 0) - параллельные прямые встречаются в одной "идеальной" точке. На этом построен SLAM в компьютерном зрении и системы pose estimation в ARKit, где одна 4x4 кодирует и поворот камеры, и её сдвиг, и перспективу.
Однородные координаты - просто хитрый трюк добавить третью единицу
Это переход в проективное пространство, где аффинные и проективные преобразования становятся обычными линейными отображениями
Возможность писать перенос как матрицу - следствие более глубокой структуры. Точки в проективной плоскости задаются с точностью до масштаба (x,y,w) ~ (kx,ky,kw), и это позволяет естественно описывать перспективу, гомографии камер и точки на бесконечности - всё в одном языке.
Зачем нужны однородные координаты в 2D геометрии?
Композиция преобразований
Главное преимущество матричного подхода - произведение матриц даёт составное преобразование. Вместо применения N матриц к каждой точке - один раз умножить N матриц, получить одну, потом применять её. В робототехнике это и есть DH-параметры (Denavit-Hartenberg, 1955): кинематическая цепь манипулятора - произведение 4-6 матриц, каждая описывает одно сочленение, итог - положение схвата.
**Порядок важен.** Матричное умножение не коммутативно: Поворот затем перенос != Перенос затем поворот M_total = M_last · ... · M_2 · M_1 Точка трансформируется: p' = M_total · p Читается справа налево - точка проходит сначала через M_1, потом M_2, и так далее.
В компьютерном зрении то же самое прячется в camera extrinsics: матрица [R|t] переводит точку из мировой системы координат в систему камеры. SLAM-алгоритмы Tesla Autopilot и ARKit оптимизируют именно эти произведения, минимизируя ошибку проекции по тысячам кадров в секунду.
Порядок умножения - артефакт записи, можно перемножать как удобно
Порядок строго определяет геометрию: M_a · M_b - сначала b, потом a. Перестановка меняет результат для всех преобразований кроме коммутирующих частных случаев
Поворот вокруг (0,0) на 90 градусов и перенос на (10,0) - типичный пример: разные порядки дают разные итоговые точки. Робот, спутавший порядок матриц в DH-цепи, промахнётся мимо детали на конвейере.
Нужно масштабировать спрайт вокруг его центра (cx, cy). Правильный порядок:
Аффинные и проективные преобразования
Аффинные преобразования сохраняют параллельность прямых и отношения длин на параллельных направлениях. Проективные - более общий класс, сохраняющий только прямолинейность (прямая остаётся прямой, но параллельные могут пересечься на линии горизонта). Именно проективные матрицы лежат в основе NeRF (Neural Radiance Fields, 2020): нейросеть учится по фотографиям сцены, обращая камерные матрицы и восстанавливая 3D-радиационное поле.
| Класс | Матрица | Что сохраняет | Пример |
|---|---|---|---|
| Изометрия | Rotation + Translation | Расстояния, углы | Физика твёрдого тела |
| Подобие | + Scale | Углы, отношения длин | Масштабирование карт |
| Аффинное | + Shear | Параллельность, отношения площадей | CSS transform, 2D sprites |
| Проективное | Полная 3x3 (8 DOF) | Прямолинейность | Гомография камеры, AR |
Spatial Transformer Networks (Jaderberg, 2015) встраивают эту матрицу прямо в архитектуру свёрточной сети: модель учится сама генерировать аффинные параметры и поворачивать вход перед классификацией. Та же идея в torchvision.transforms.RandomAffine - data augmentation для ImageNet.
Какое преобразование НЕ является аффинным?
Ключевые идеи
- **Поворот, масштаб, отражение** - матрицы 2x2; перенос требует однородных координат
- **Однородные координаты:** (x,y) → (x,y,1), матрица 3x3 включает перенос
- **Композиция:** M_total = M_n·...·M_1 - порядок умножения справа налево
- **Аффинные** сохраняют параллельность; **проективные** - только прямолинейность
Связанные темы
Матрицы преобразований - переход к 3D и проективной геометрии:
- Пространственная геометрия — 3D: матрицы 4x4 в однородных координатах
- Проективная геометрия — Гомография = 3x3 матрица (8 DOF) над однородными координатами
- Векторная геометрия — Матрицы преобразований - линейные операторы над векторами
Вопросы для размышления
- Почему порядок преобразований важен? Какой пример показывает, что поворот+перенос != перенос+поворот?
- Как вычисляется обратное преобразование? Что такое обратная матрица в контексте аффинных преобразований?
- Почему в WebGL используют матрицы 4x4 даже для 2D-графики?
Связанные уроки
- la-07-matrix-multiply — Композиция преобразований - произведение матриц
- la-13-linear-maps — Аффинные отображения как линейные операторы
- geo-12 — Гомография и проективные преобразования над 3x3
- ml-29-cnn — Spatial transformer networks и data augmentation
- cv-05 — Camera extrinsics и SLAM используют те же 4x4
- la-01-vectors-intro