TL;DR
Результаты неверны, потому что в GNU Octave imresize
была ошибка. Недавно это было исправлено для билинейной интерполяции (отчет об ошибке, совершить). Прокрутите вниз до Интерполяции пикселей для правильного объяснения того, как изображения интерполируются.
Интерполяция образцов
Начнем с линейной интерполяции отсчетов:
0 1/3 2/3 1
| | | |
a=1----+----+----2=b
Вы переходите от a к b, используя
f(x) = (1 - x) * a + x * b.
Некоторые примеры:
- f(0) = (1 - 0) * a + 0 * b = a = 1
- f(1/3) = (1 - 1/3) * a + 1/3 * b = 2/3 + 2/3 = 4/3 = 1.3333
- f(1/2) = (1 - 1/2) * a + 1/2 * b = (a + b) / 2 = 1.5
- f(2/3) = (1 - 2/3) * a + 2/3 * b = 1/3 + 4/3 = 5/3 = 1.6667
- f(1) = (1 - 1) * a + 1 * b = b = 2
Это соответствует первой строке вашего первого примера. При билинейной интерполяции используется простая линейная интерполяция по осям x или y. Обычно простая линейная интерполяция не используется по диагонали или в любом другом направлении (ваш первый пример - вырожденный случай).
0 1/3 1
| | | |
0 a=1---f(x)--+----2=b
| | | |
-+----+----+----+-
| | | |
2/3 -+---???---+----+-
| | | |
1 c=3---g(x)--+----4=d
| | | |
Как тогда рассчитываются другие баллы? Мы используем простую линейную интерполяцию для верхней и нижней строки в направлении x, а затем интерполируем результаты в направлении y:
- В направлении x, верхний ряд: f (x) = (1 - x) * a + x * b, например: f (1/3) = 4/3 = 1,3333
- В направлении x нижний ряд: g (x) = (1 - x) * c + x * d, например: g (1/3) = 10/3 = 3,3333
- В направлении y столбец интерполяции: h (y) = (1 - y) * f (x) + y * g (x), например: h (2/3) = 8/3 = 2,6667
Глядя на последнее уравнение, мы могли бы также подставить f (x) и g (x) и получить:
h(x, y) = (1 - x) * (1 - y) * a + x * (1 - y) * b + (1 - x) * y * c + x * y * d
Это то, что у вас есть.
Во втором примере точки немного отличаются, потому что вы преобразовываете из 4 точек в 6 в каждом направлении:
old: 0 1 2 3 (sample grid)
| | | |
+-----+---+-+-----+-+---+-----+
| | | | | |
new: 0 3/5 6/5 9/5 12/5 3 (interpolation grid)
Это верно для направлений x и y во втором примере. Чтобы использовать приведенную выше формулу, вы должны сопоставить каждый квадрат с [0, 1] x [0, 1].
Это теория. Octave использует interp2
для внутренней билинейной интерполяции. Чтобы использовать interp2
, вы указываете матрицу с выборками и сетку, которая определяет точки интерполяции:
A = [1, 2;
3, 4];
xi = linspace(1, size(A, 2), 4);
yi = linspace(1, size(A, 1), 4)';
B = interp2(A, xi, yi)
Это дает результаты, которые вы получили, но они неверны!
Интерполяция пикселей
Основы билинейной интерполяции, как объяснено выше, по-прежнему действительны, но сетка интерполяции неверна. Это потому, что изображение состоит не из точек выборки, а из пикселей. Пиксели - это области, представленные ее средним значением. На самом деле пиксели изображения выглядят так:
0.5 1 1.5 2 2.5
0.5 +-------------------+-------------------+
| | |
| | |
| | |
1 | o | o |
| | |
| | |
| | |
1.5 +-------------------+-------------------+
| | |
| | |
| | |
2 | o | o |
| | |
| | |
| | |
2.5 +-------------------+-------------------+
Таким образом, площадь верхнего левого пикселя составляет [0,5, 1,5] x [0,5, 1,5] с центром в (1, 1). И то, что вы хотите, увеличивая масштаб до 2, - это следующие новые пиксели (в координатном пространстве старой сетки, поскольку изображение покрывает все ту же область):
0.5 0.75 1 1.25 1.5 1.75 2 2.25 2.5
0.5 +---------+---------+---------+---------+
| | | | |
0.75 | x | x | x | x |
| | | | |
1 +---------o---------+---------o---------+
| | | | |
1.25 | x | x | x | x |
| | | | |
1.5 +---------+---------+---------+---------+
| | | | |
1.75 | x | x | x | x |
| | | | |
2 +---------o---------+---------o---------+
| | | | |
2.25 | x | x | x | x |
| | | | |
2.5 +---------+---------+---------+---------+
Теперь вы берете новые центры x
как сетку интерполяции, а старые центры o
как сетку образца. Вы видите, что новые пиксели границы действительно нуждаются в экстраполяции. Мы предполагаем, что он экстраполирует константу, поэтому мы можем дополнить массив, чтобы снова выполнить интерполяцию или ограничить сетку интерполяции. В качестве кода с использованием interp2
вы можете:
A = [1, 2;
3, 4];
xi = linspace(0.75, 2.25, 4);
yi = linspace(0.75, 2.25, 4)';
xi(xi < 1) = 1; xi(xi > 2) = 2;
yi(yi < 1) = 1; yi(yi > 2) = 2;
B = interp2(A, xi, yi)
Вот более общее решение (действительно только для целочисленных размеров вывода), основанное на комментариях Амро ниже его ответ. Если вы разрешаете масштабные коэффициенты, которые приводят к выходному размеру с плавающей запятой.
При нецелочисленных выходных размерах количество новых пикселей будет таким, что последний пиксель будет перекрываться. Так, например, с коэффициентом масштабирования 5/4 = 1,25 размер пикселя будет 1 / (5/4) = 4/5 = 0,8. Следовательно, масштабирование изображения 2x2 на 1,25 дает изображение 3x3. Центры старых пикселей (сетка выборки) находятся в точках 1 и 2, а центры новых пикселей (сетка интерполяции) находятся в точках 0,9, 1,7 и 2,5.
0.5 1.5 2.5
| 1 | 2 |
old: +---------o---------+---------o---------+
new: +-------x-------+-------x-------+-------x-------+
| 0.9 | 1.7 | 2.5 |
0.5 1.3 2.1 2.9
Вот код, чтобы показать это:
img = [1, 2;
3, 4];
% make interpolation grid
scale = 1.25
pixel_size = 1 / scale
out_size = ceil(size(img) / pixel_size)
xi = 0.5 + pixel_size / 2 + (0:out_size(1)-1) / scale
yi = 0.5 + pixel_size / 2 + (0:out_size(2)-1) / scale
% limit interpolation grid to sample grid bounds
xi(xi < 1) = 1; xi(xi > size(img, 2)) = size(img, 2)
yi(yi < 1) = 1; yi(yi > size(img, 1)) = size(img, 1)
% interpolate
scaled_interp = interp2(img, xi, yi', 'linear')
% Octave's imresize does not support anti-aliasing yet
scaled_resize_octave = imresize(img, scale, 'bilinear')
% Matlab's imresize uses anti-aliasing for downscaling, switch off to keep is simple
scaled_resize_matlab = imresize(img, scale, 'bilinear', 'Antialiasing', false)
% yields:
% 1.0000 1.7000 2.0000
% 2.4000 3.1000 3.4000
% 3.0000 3.7000 4.0000
Это все, что касается изменения размера с помощью билинейной интерполяции. Для бикубической интерполяции Matlab использует симметричное заполнение и сверточный алгоритм, который взвешивает окрестности 4x4. Octave ведет себя иначе (патч поступает).
person
John
schedule
11.04.2021