Вращение изображения по Matlab без использования imrotate

Я пытаюсь повернуть изображение с помощью Matlab без использования функции imrotate. Я на самом деле сделал это, используя матрицу преобразования. Но это не достаточно хорошо. Проблема в том, что повернутое изображение «скользящее». Позвольте мне рассказать вам фотографии.

Это мое изображение, которое я хочу повернуть:

введите описание изображения здесь

Но когда я поворачиваю его, например, на 45 gradleусов, он становится следующим:

введите описание изображения здесь

Я спрашиваю, почему это происходит. Вот мой код, есть ли математические или программные ошибки?

image=torso; %image padding [Rows, Cols] = size(image); Diagonal = sqrt(Rows^2 + Cols^2); RowPad = ceil(Diagonal - Rows) + 2; ColPad = ceil(Diagonal - Cols) + 2; imagepad = zeros(Rows+RowPad, Cols+ColPad); imagepad(ceil(RowPad/2):(ceil(RowPad/2)+Rows-1),ceil(ColPad/2):(ceil(ColPad/2)+Cols-1)) = image; degree=45; %midpoints midx=ceil((size(imagepad,1)+1)/2); midy=ceil((size(imagepad,2)+1)/2); imagerot=zeros(size(imagepad)); %rotation for i=1:size(imagepad,1) for j=1:size(imagepad,2) x=(i-midx)*cos(degree)-(j-midy)*sin(degree); y=(i-midx)*sin(degree)+(j-midy)*cos(degree); x=round(x)+midx; y=round(y)+midy; if (x>=1 && y>=1) imagerot(x,y)=imagepad(i,j); % k degrees rotated image end end end figure,imagesc(imagerot); colormap(gray(256)); 

Причина, по которой у вас есть дыры в вашем изображении, – это то, что вы вычисляете местоположение в imagerot каждого пикселя в imagepad . Вам нужно делать вычисления по-другому. То есть для каждого пикселя в интерполяторе imagepad в imagepad . Для этого вам просто нужно применить обратное преобразование, которое в случае матрицы вращения является просто транспонированием матрицы (просто измените знак на каждый sin и переведите другой путь).

Петля над пикселями в imagerot :

 imagerot=zeros(size(imagepad)); % midx and midy same for both for i=1:size(imagerot,1) for j=1:size(imagerot,2) x= (i-midx)*cos(rads)+(j-midy)*sin(rads); y=-(i-midx)*sin(rads)+(j-midy)*cos(rads); x=round(x)+midx; y=round(y)+midy; if (x>=1 && y>=1 && x<=size(imagepad,2) && y<=size(imagepad,1)) imagerot(i,j)=imagepad(x,y); % k degrees rotated image end end end 

Также обратите внимание, что ваш midx и midy нужно рассчитывать с size(imagepad,2) и size(imagepad,1) соответственно, так как первый размер относится к числу строк (высота), а второй - к ширине.

ПРИМЕЧАНИЕ. Тот же подход применяется, когда вы решите принять интерполяционную схему, отличную от ближайшего соседа, как в примере Роди с линейной интерполяцией.

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

 imagepad = imread('peppers.png'); [nrows ncols nslices] = size(imagepad); midx=ceil((ncols+1)/2); midy=ceil((nrows+1)/2); Mr = [cos(pi/4) sin(pi/4); -sin(pi/4) cos(pi/4)]; % eg 45 degree rotation % rotate about center [XY] = meshgrid(1:ncols,1:nrows); XYt = [X(:)-midx Y(:)-midy]*Mr; XYt = bsxfun(@plus,XYt,[midx midy]); xout = round(XYt(:,1)); yout = round(XYt(:,2)); % nearest neighbor! outbound = yout<1 | yout>nrows | xout<1 | xout>ncols; zout=repmat(cat(3,1,2,3),nrows,ncols,1); zout=zout(:); xout(xout<1) = 1; xout(xout>ncols) = ncols; yout(yout<1) = 1; yout(yout>nrows) = nrows; xout = repmat(xout,[3 1]); yout = repmat(yout,[3 1]); imagerot = imagepad(sub2ind(size(imagepad),yout,xout,zout(:))); % lookup imagerot = reshape(imagerot,size(imagepad)); imagerot(repmat(outbound,[1 1 3])) = 0; % set background value to [0 0 0] (black) 

Чтобы изменить приведенную выше линейную интерполяцию, вычислите 4 соседних пикселя для каждой координаты в XYt и выполните взвешенную сумму, используя продукт дробных компонентов в качестве весов. Я оставлю это как упражнение, так как это только послужит для раздувания моего ответа дальше вне сферы вашего вопроса. 🙂

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

Поворот по отображению области, как указано ниже ( это хорошая ссылка), намного лучше сохраняет цвет.

Но: обратите внимание, что это будет работать только на изображениях с оттенками серого / RGB, но не на цветных изображениях, подобных тем, которые вы, кажется, используете.

 image = imread('peppers.png'); figure(1), clf, hold on subplot(1,2,1) imshow(image); degree = 45; switch mod(degree, 360) % Special cases case 0 imagerot = image; case 90 imagerot = rot90(image); case 180 imagerot = image(end:-1:1, end:-1:1); case 270 imagerot = rot90(image(end:-1:1, end:-1:1)); % General rotations otherwise % Convert to radians and create transformation matrix a = degree*pi/180; R = [+cos(a) +sin(a); -sin(a) +cos(a)]; % Figure out the size of the transformed image [m,n,p] = size(image); dest = round( [1 1; 1 n; m 1; mn]*R ); dest = bsxfun(@minus, dest, min(dest)) + 1; imagerot = zeros([max(dest) p],class(image)); % Map all pixels of the transformed image to the original image for ii = 1:size(imagerot,1) for jj = 1:size(imagerot,2) source = ([ii jj]-dest(1,:))*R.'; if all(source >= 1) && all(source <= [mn]) % Get all 4 surrounding pixels C = ceil(source); F = floor(source); % Compute the relative areas A = [... ((C(2)-source(2))*(C(1)-source(1))),... ((source(2)-F(2))*(source(1)-F(1))); ((C(2)-source(2))*(source(1)-F(1))),... ((source(2)-F(2))*(C(1)-source(1)))]; % Extract colors and re-scale them relative to area cols = bsxfun(@times, A, double(image(F(1):C(1),F(2):C(2),:))); % Assign imagerot(ii,jj,:) = sum(sum(cols),2); end end end end subplot(1,2,2) imshow(imagerot); 

Вывод:

введите описание изображения здесь

Поворачивает цветное изображение в соответствии с углом, заданным пользователем, без кадрирования изображения в Matlab.

Вывод этой программы аналогичен выходу встроенной команды «imrotate». Эта программа динамически создает фон в соответствии с угловым вводом, заданным пользователем. Используя матрицу поворота и смещение начала, мы получаем связь между координатами начального и конечного изображений. Отношение между координаты начального и конечного изображений, теперь мы сопоставляем значения интенсивности для каждого пикселя.

 img=imread('img.jpg'); [rowsi,colsi,z]= size(img); angle=45; rads=2*pi*angle/360; %calculating array dimesions such that rotated image gets fit in it exactly. % we are using absolute so that we get positve value in any case ie.,any quadrant. rowsf=ceil(rowsi*abs(cos(rads))+colsi*abs(sin(rads))); colsf=ceil(rowsi*abs(sin(rads))+colsi*abs(cos(rads))); % define an array withcalculated dimensionsand fill the array with zeros ie.,black C=uint8(zeros([rowsf colsf 3 ])); %calculating center of original and final image xo=ceil(rowsi/2); yo=ceil(colsi/2); midx=ceil((size(C,1))/2); midy=ceil((size(C,2))/2); % in this loop we calculate corresponding coordinates of pixel of A % for each pixel of C, and its intensity will be assigned after checking % weather it lie in the bound of A (original image) for i=1:size(C,1) for j=1:size(C,2) x= (i-midx)*cos(rads)+(j-midy)*sin(rads); y= -(i-midx)*sin(rads)+(j-midy)*cos(rads); x=round(x)+xo; y=round(y)+yo; if (x>=1 && y>=1 && x<=size(img,1) && y<=size(img,2) ) C(i,j,:)=img(x,y,:); end end end imshow(C); 

Проверь это.

это самый быстрый способ, который вы можете сделать. это выход

 img = imread('Koala.jpg'); theta = pi/10; rmat = [ cos(theta) sin(theta) 0 -sin(theta) cos(theta) 0 0 0 1]; mx = size(img,2); my = size(img,1); corners = [ 0 0 1 mx 0 1 0 my 1 mx my 1]; new_c = corners*rmat; T = maketform('affine', rmat); %# represents translation img2 = imtransform(img, T, ... 'XData',[min(new_c(:,1)) max(new_c(:,1))],... 'YData',[min(new_c(:,2)) max(new_c(:,2))]); subplot(121), imshow(img); subplot(122), imshow(img2); 
  • Объединение двух изображений
  • Квадратное обнаружение не находит квадратов
  • Чтение проблем JPEG Метаданные (ориентация)
  • Как программно изменить оттенок UIImage?
  • opencv рисует 2d гистограмму
  • доступ к многоканальному элементу opencv
  • пропорции перспективно-деформированного прямоугольника
  • Сглаживание зубчатого пути
  • Обработка изображений: улучшение алгоритма для распознавания «Coca-Cola Can»
  • почему список шрифтов пуст для imagemagick?
  • Простое обнаружение объектов с использованием OpenCV и машинного обучения
  • Давайте будем гением компьютера.