В этом примере показано, как создать tform
struct, которая представляет простое преобразование сдвига и затем применяет его к изображению. Мы исследуем, как преобразование влияет на прямые линии и круги, а затем используем его как транспортное средство, чтобы исследовать различные опции заполнения изображений, которые могут использоваться с imtransform
и tformarray
.
В две размерностей простое преобразование сдвига, которое отображает пару входа координат [u v]
к паре выхода координат [x y]
имеет форму
где a
является константой.
Любой простой сдвиг является частным случаем аффинного преобразования. Вы можете легко проверить, что
приводит к значениям для x
и y
что вы получили от первых двух уравнений.
Настройка a
= 0,45, мы создадим аффин tform
struct с использованием maketform
.
a = 0.45;
T = maketform('affine', [1 0 0; a 1 0; 0 0 1] );
Мы выбираем, читаем, и просматриваем, и изображение для преобразования.
A = imread('football.jpg'); h1 = figure; imshow(A); title('Original Image');
Мы выбираем оттенок оранжевого цвета в качестве значения.
orange = [255 127 0]';
Мы готовы использовать T
для преобразования A
. Мы можем позвонить imtransform
следующим образом:
B = imtransform(A,T,'cubic','FillValues',orange);
но это расточительно, поскольку мы применяли бы кубическую интерполяцию как по столбцам, так и по строкам. (С нашим чистым преобразованием сдвига, нам действительно нужно только интерполироваться вдоль каждой строки.) Вместо этого мы создаем и используем ресамплер, который применяет кубическую интерполяцию вдоль строк, но просто использует ближайшую соседнюю интерполяцию вдоль столбцов, затем вызывает imtransform
и отобразите результат.
R = makeresampler({'cubic','nearest'},'fill'); B = imtransform(A,T,R,'FillValues',orange); h2 = figure; imshow(B); title('Sheared Image');
Преобразование сетки прямых линий или массива кругов с tformfwd
является хорошим способом понять преобразование (пока оно имеет как прямые, так и обратные функции).
Задайте сетку линий, покрывающих оригинальное изображение, и отобразите ее над изображением Затем используйте tformfwd
чтобы применить чистый сдвиг к каждой линии в сетке и отобразить результат на срезанном изображении.
[U,V] = meshgrid(0:64:320,0:64:256); [X,Y] = tformfwd(T,U,V); gray = 0.65 * [1 1 1]; figure(h1); hold on; line(U, V, 'Color',gray); line(U',V','Color',gray);
figure(h2); hold on; line(X, Y, 'Color',gray); line(X',Y','Color',gray);
То же самое можно сделать с массивом кругов.
gray = 0.65 * [1 1 1]; for u = 0:64:320 for v = 0:64:256 theta = (0 : 32)' * (2 * pi / 32); uc = u + 20*cos(theta); vc = v + 20*sin(theta); [xc,yc] = tformfwd(T,uc,vc); figure(h1); line(uc,vc,'Color',gray); figure(h2); line(xc,yc,'Color',gray); end end
Когда мы применили преобразование сдвига, imtransform
заполнены оранжевые треугольники слева и справа, где данных не было. Это потому, что мы задали метод pad для 'fill'
при вызове makeresampler
. Существует в общей сложности пять различных вариантов метода заполнения ('fill'
, 'replicate'
, 'bound'
, 'circular'
, и 'symmetric'
). Здесь мы сравниваем первые три.
Во-первых, чтобы лучше взглянуть на то, как 'fill'
опция сработала, используйте 'XData'
и 'YData'
опции в imtransform
чтобы форсировать некоторое дополнительное пространство вокруг выходного изображения.
R = makeresampler({'cubic','nearest'},'fill'); Bf = imtransform(A,T,R,'XData',[-49 500],'YData',[-49 400],... 'FillValues',orange); figure, imshow(Bf); title('Pad Method = ''fill''');
Теперь попробуйте 'replicate'
метод (не нужно задавать значения заливки в этом случае).
R = makeresampler({'cubic','nearest'},'replicate'); Br = imtransform(A,T,R,'XData',[-49 500],'YData', [-49 400]); figure, imshow(Br); title('Pad Method = ''replicate''');
И попробуйте 'bound'
способ.
R = makeresampler({'cubic','nearest'}, 'bound'); Bb = imtransform(A,T,R,'XData',[-49 500],'YData',[-49 400],... 'FillValues',orange); figure, imshow(Bb); title('Pad Method = ''bound''');
Результаты с 'fill'
и 'bound'
выглядите очень похожи, но присмотритесь и вы увидите, что ребра более гладкие с 'fill'
. Это потому, что вход изображение заполнено значениями заливки, тогда кубическая интерполяция применяется через ребро, смешивая значения заливки и изображения. Напротив, 'bound'
распознает строгий контур между внутренней и внешней частями входа изображения. Точки, падающие снаружи, заполняются. Точки, падающие внутрь, интерполируются, используя репликацию, когда они находятся рядом с ребром. Внешний вид помогает показать это более четко. Выбираем XData
и YData
чтобы скобить точку рядом с нижним правым углом изображения, в выходное изображение пространстве, измените размер с 'nearest'
для сохранения внешнего вида отдельных пикселей.
R = makeresampler({'cubic','nearest'},'fill'); Cf = imtransform(A,T,R,'XData',[423 439],'YData',[245 260],... 'FillValues',orange); R = makeresampler({'cubic','nearest'},'bound'); Cb = imtransform(A,T,R,'XData',[423 439],'YData',[245 260],... 'FillValues',orange); Cf = imresize(Cf,12,'nearest'); Cb = imresize(Cb,12,'nearest'); figure; subplot(1,2,1); imshow(Cf); title('Pad Method = ''fill'''); subplot(1,2,2); imshow(Cb); title('Pad Method = ''bound''');
Оставшиеся два метода заполнения 'circular'
(циклическое повторение в каждой размерности) и 'symmetric'
(циклическое повторение изображения с добавленным зеркальным изображением). Чтобы показать больше шаблона, который появляется, мы переопределяем преобразование, чтобы сократить шкалу вдвое.
Thalf = maketform('affine',[1 0; a 1; 0 0]/2); R = makeresampler({'cubic','nearest'},'circular'); Bc = imtransform(A,Thalf,R,'XData',[-49 500],'YData',[-49 400],... 'FillValues',orange); figure, imshow(Bc); title('Pad Method = ''circular''');
R = makeresampler({'cubic','nearest'},'symmetric'); Bs = imtransform(A,Thalf,R,'XData',[-49 500],'YData',[-49 400],... 'FillValues',orange); figure, imshow(Bs); title('Pad Method = ''symmetric''');