Поворот изображения без панели инструментов обработки изображений - PullRequest
8 голосов
/ 15 июня 2011

Я хотел бы повернуть изображение без квадрата с помощью Matlab:

  • без использования функции imrotate, поскольку она является частью панели инструментов обработки изображений,
  • с параметром loose, что означает, что размер вывода отличается от размера входного изображения,
  • и с не слишком медленной функцией по сравнению с imrotate.

Я уже нашел функцию , чтобы сделать это (просто замените imshow и bestblk вашими собственными функциями, чтобы не использовать панель инструментов), но на самом деле это медленно для больших изображений. Мой подход состоит в том, чтобы избегать создания петель и максимально полагаться на interp2.


Подпись функции будет:

imOutput = my_imrotate(imInput, theta_degres, interpolation, bbox)

где:

  • interpolation будет bilinear, bicubic или nearest,
  • bbox будет crop или loose.

Crop

У меня уже есть хороший результат с параметром crop, но мне не удается найти смещение для параметра loose.

Вот код для параметра crop, где Z - это вход, а Zi - это выход:

Z = double(imInput);
sz = size(Z);
[X,Y] = meshgrid(1:sz(2), 1:sz(1));
%# Center
c = sz(end:-1:1)/2;
%# Angle
t = theta_degres*pi/180;
%# Rotation
ct = cos(t);
st = sin(t);
Xi = c(1) + ct*(X-c(1))-st*(Y-c(2));
Yi = c(2) + st*(X-c(1))+ct*(Y-c(2));
%# Rotation
Zi = interp2(X, Y, Z, Xi, Yi);

Сыпучие

Моя идея состоит в том, чтобы вычислить размер кадра, который будет содержать исходное изображение и повернутое изображение, а затем:

  1. дополняет исходное изображение таким образом, чтобы иметь изображение, размер которого равен размеру рамки,
  2. используйте interp2 для дополненного изображения,
  3. обрезать получившееся изображение так, чтобы получилось повернутое изображение без остатков отступов.

Чтобы получить размер повернутого изображения с помощью параметра loose, я вычисляю rotation_matrix и вызываю rotate_points по координатам углов p входного изображения:

rotation_matrix = [ct, -st; st, ct];
rotate_points = @(p) bsxfun(@plus, c', rotation_matrix * bsxfun(@minus, p, c)')';

Любая помощь будет принята с благодарностью.


Редактировать: Используя решение, представленное в ответе ниже, и следующий код, кажется, работает правильно:

%# See the answer below
[sz1,sz2] = size(Z);
sz1New = sz1*cos(t)+sz2*sin(t);
sz2New = sz2*cos(t)+sz1*sin(t);
[Xi,Yi] = meshgrid(-(sz2New-1)/2:(sz2New-1)/2,-(sz1New-1)/2:(sz1New-1)/2);
%# now all that's left is rotating Xi,Yi - I have already subtracted the center

%# My little piece of additional code
Xii = (1+sz2)/2 + ct*Xi - st*Yi;
Yii = (1+sz1)/2 + st*Xi + ct*Yi; 
Zi = interp2(X, Y, Z, Xii, Yii);

1 Ответ

4 голосов
/ 15 июня 2011

Для версии loose все, что вам нужно сделать, это выяснить, сколько отступов вам нужно.Вы можете легко оценить это с небольшой геометрией:

Если вы рисуете «свободный» прямоугольник, вы по существу добавляете четыре прямоугольных треугольника к исходному прямоугольнику.Гипотенузы треугольников - это стороны прямоугольника.Если вы можете определить две другие стороны, вы можете легко рассчитать длину новых сторон и, таким образом, отступы.К счастью, одним из углов прямоугольного треугольника является именно ваш угол поворота.

Как выясняется, вам даже не нужно явно вычислять заполнение - вы просто создаете больший массив Xi, Yi, который имеетразмер «свободного» изображения.

Таким образом:

[sz1,sz2] = size(Z);
sz1New = sz1*cos(t)+sz2*sin(t);
sz2New = sz2*cos(t)+sz1*sin(t);
[Xi,Yi] = meshgrid(-(sz2New-1)/2:(sz2New-1)/2,-(sz1New-1)/2:(sz1New-1)/2);
%# now all that's left is rotating Xi,Yi - I have already subtracted the center
...