interp2 bilinear matlab image-processing interpolation

bilinear - Rotación de imagen por Matlab sin utilizar imrotate.



bilinear interpolation matlab (4)

El método que está utilizando (rotar por muestreo) es el más rápido y simple, pero también el menos preciso.

El mapa de rotación por área, como se indica a continuación ( this es una buena referencia), es mucho mejor para preservar el color.

Pero: tenga en cuenta que esto solo funcionará en imágenes en escala de grises / RGB, pero NO en imágenes con formato de color como la que parece estar usando.

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; m n]*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 <= [m n]) % 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);

Salida:

Estoy tratando de rotar una imagen con Matlab sin usar la función de imrotación. De hecho, lo hice utilizando la matriz de transformación. Pero no es lo suficientemente bueno. El problema es que la imagen girada es "deslizante". Déjame que te cuente las imágenes.

Esta es mi imagen que quiero rotar:

Pero cuando lo giro, por ejemplo 45 grados, se convierte en esto:

Estoy preguntando por qué está sucediendo esto. Aquí está mi código, ¿hay algún error matemático o de programación al respecto?

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));


Gira la imagen en color según el ángulo dado por el usuario sin ningún recorte de la imagen en matlab.

La salida de este programa es similar a la salida del comando incorporado "imrotate" .Este programa crea dinámicamente el fondo de acuerdo con el ángulo de entrada dado por el usuario. Al utilizar la matriz de rotación y el cambio de origen, obtenemos una relación entre las coordenadas de la imagen inicial y final. Coordenadas de la imagen inicial y final, ahora mapeamos los valores de intensidad para cada píxel.

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);


La razón por la que tiene agujeros en su imagen es porque está calculando la ubicación en imagerot de cada píxel en imagepad . Necesitas hacer el cálculo al revés. Es decir, para cada píxel en imagerot interpola en imagepad . Para hacer esto, solo necesitas aplicar la transformada inversa, que en el caso de una matriz de rotación es solo la transposición de la matriz (solo cambia el signo en cada sin y traduce al otro lado).

Bucle sobre píxeles en 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

También tenga en cuenta que su midx y midy deben calcularse con el size(imagepad,2) y el size(imagepad,1) respectivamente, ya que la primera dimensión se refiere al número de filas (altura) y la segunda a la anchura.

NOTA: El mismo enfoque se aplica cuando decide adoptar un esquema de interpolación distinto del vecino más cercano, como en el ejemplo de Rody con interpolación lineal.

EDITAR : Supongo que está utilizando un bucle con fines demostrativos, pero en la práctica no hay necesidad de bucles. Este es un ejemplo de la interpolación del vecino más cercano (lo que está usando), manteniendo la imagen del mismo tamaño, pero puede modificarla para producir una imagen más grande que incluya toda la imagen de origen:

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)]; % e.g. 45 degree rotation % rotate about center [X Y] = 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)

Para modificar lo anterior a interpolación lineal, calcule los 4 píxeles XYt a cada coordenada en XYt y realice una suma ponderada utilizando el producto de componentes fraccionarios como los pesos. Dejaré eso como un ejercicio, ya que solo serviría para inflar mi respuesta más allá del alcance de su pregunta. :)


Mira esto.

Esta es la forma más rápida que puedes hacer.

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);