【數字圖像處理】MATLAB實現圖像旋轉的三種算法

圖像位置變換——圖像旋轉的MATLAB實現


代碼實現

1)旋轉方法0

缺點:容易產生空洞,效果不佳

% I = imread('img\peppers.png');
% [im] = dip(I,30);
% function [im]=rotate0(I,angle)
function [im]=dip(I,angle)   % 輸入:圖像矩陣I,旋轉角度angle
[m,n,d] = size(I);           % 獲得原圖像尺寸,d爲顏色通道

% 由於matlab中cos,sin角度爲弧度,故進行轉換
a = angle*pi/180;

% 圖像四個頂點行座標、列座標(逆時針)
r1 = 1; r2 = m; r3 = m; r4 = 1;
c1 = 1; c2 = 1; c3 = n; c4 = n;
x = [r1,r2,r3,r4]; % 向量
y = [c1,c2,c3,c4];

% 根據旋轉公式,得旋轉後的座標(x,y爲原始圖像座標,x1,y1爲旋轉後坐標)
x1 = round(x*cos(a)-y*sin(a));
y1 = round(x*sin(a)+y*cos(a));

% 計算x1 y1的最大、最小值
x1_max = max(x1);
y1_max = max(y1);
x1_min = min(x1);
y1_min = min(y1);

% 得出畫布擴展後的大小爲m2,n2
m2 = x1_max - x1_min + 1;
n2 = y1_max - y1_min + 1;

% 計算x和y方向平移量det_x,det_y
if x1_min<=0
    delta_x = abs(x1_min)+1;
else
    delta_x = 0;
end
if y1_min<=0
    delta_y = abs(y1_min)+1;
else
    delta_y = 0;
end

im = zeros(m2,n2,d); % 初始化新圖矩陣

% 對原圖的每一行,每一列,根據旋轉公式和平移量,得原新圖對應座標
for i=1:m
    for j=1:n
        x = round(i*cos(a)-j*sin(a)) + delta_x;
        y = round(i*sin(a)+j*cos(a)) + delta_y;
        im(x,y,:)=I(i,j,:);
    end
end

figure,imshow(uint8(I));title('原圖');
figure,imshow(uint8(im));title('經旋轉方法0旋轉後的圖像');

end

2)旋轉方法1插值法:空洞填充

% I = imread('img\peppers.png');
% [im] = dip(I,30);
% function [im]=rotate1(I,angle)

function [im]=dip(I,angle) 
[m,n,d] = size(I); 
        
% 由於matlab中cos,sin角度爲弧度,故進行轉換
a = angle*pi/180;

% 原圖像四個頂點行座標、列座標(逆時針)
r1 = 1; r2 = m; r3 = m; r4 = 1;
c1 = 1; c2 = 1; c3 = n; c4 = n;
x = [r1,r2,r3,r4];         % 向量
y = [c1,c2,c3,c4];

% 根據旋轉公式,得旋轉後的座標(x,y爲原始圖像座標,x1,y1爲旋轉後坐標)
x1 = round(x*cos(a)-y*sin(a));
y1 = round(x*sin(a)+y*cos(a));

% 計算x1 y1的最大、最小值
x1_max = max(x1);
y1_max = max(y1);
x1_min = min(x1);
y1_min = min(y1);

% 得出畫布擴展後的大小爲m2,n2
m2 = x1_max - x1_min + 1;
n2 = y1_max - y1_min + 1;

% 計算x和y方向平移量det_x,det_y
if x1_min<=0
    delta_x = abs(x1_min)+1;
else
    delta_x = 0;
end
if y1_min<=0
    delta_y = abs(y1_min)+1;
else
    delta_y = 0;
end

% 初始化新圖矩陣
im = ones(m2,n2,d)*(-1); % 要進行黑洞填充爲判斷非背景點,畫布初始化-1(非法值)

% 對原圖的每一行,每一列,根據旋轉公式和平移量,得原新圖對應座標
for i=1:m
    for j=1:n
        x = round(i*cos(a)-j*sin(a)) + delta_x;
        y = round(i*sin(a)+j*cos(a)) + delta_y;
        im(x,y,:)=I(i,j,:);
    end
end

% 進行插值--R通道
im_1 = im(:,:,1);

% 對新圖的每一行
for i=1:m2
    % 找出新圖第i行所有非背景點的行列座標
    [x_1,y_1] = find(im_1(i,:)>0); % 找出所有大於0的點
    
    % 求第i行所有非背景點的列座標的起止值
    y1_min = min(y_1);
    y1_max = max(y_1);
    
    %(y1_min,y_1max)範圍內進行插值,對y1_min,y_1max之間的每一個像素點
    for j=y1_min+1:y1_max
        % 若爲背景點,將前一個點賦給該點
        if(im(i,j)<0)
            im(i,j,:)=im(i,j-1,:);
        end
    end
end

figure,imshow(uint8(I));title('原圖');
figure,imshow(uint8(im));title('經旋轉方法1插值法旋轉後的圖像');

end

3)旋轉方法2反變換

% I = imread('img\peppers.png');
% [im] = dip(I,30);
% function [im]=rotate2(I,angle)
function [im]=dip(I,angle) 
[m,n,d] = size(I); 

a = angle*pi/180;

r1 = 1; r2 = m; r3 = m; r4 = 1;
c1 = 1; c2 = 1; c3 = n; c4 = n;
x = [r1,r2,r3,r4]; 
y = [c1,c2,c3,c4];

x1 = round(x*cos(a)-y*sin(a));
y1 = round(x*sin(a)+y*cos(a));

x1_max = max(x1);
y1_max = max(y1);
x1_min = min(x1);
y1_min = min(y1);

% 得出畫布擴展後的大小爲m2,n2
m2 = x1_max - x1_min + 1;
n2 = y1_max - y1_min + 1;

% 計算x和y方向平移量det_x,det_y
if x1_min<=0
    delta_x = abs(x1_min)+1;
else
    delta_x = 0;
end
if y1_min<=0
    delta_y = abs(y1_min)+1;
else
    delta_y = 0;
end

% 初始化新圖矩陣
im = ones(m2,n2,d)*(-1); 

% 對新圖的每一行,每一列,根據旋轉反變換公式和平移量,得原新圖對應座標
for i=1:m2
    for j=1:n2
        % 原圖→新圖,座標+deltax,+delta_y
        % 新圖→原圖 反變換,因而座標要先-delta_x,-delta_y
        x = round((i-delta_x)*cos(a)+(j-delta_y)*sin(a));
        y = round(-(i-delta_x)*sin(a)+(j-delta_y)*cos(a));
        if(x>0 && x<=m && y>0 && y<=n)
            im(i,j,:)=I(x,y,:);
        end
    end
end

figure,imshow(uint8(I));title('原圖');
figure,imshow(uint8(im));title('經旋轉方法2反變換旋轉後的圖像');

end

命令行窗口輸入如下代碼:

I = imread('img\peppers.png');
[im] = dip(I,30);

代碼執行結果:
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章