• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

Matlab实现imrotate函数功能

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

算法分析

  1. 开辟新矩阵存放旋转后的图像。计算公式如下,H为原图像行,W原图像列,a为旋转角度,a是钝角时,三角函数需要加上绝对值
DH = H * abs(cos(a)) + W * abs(sin(a));  
DW = H * abs(sin(a)) + W * abs(cos(a));
  1. 计算旋转后的坐标(旋转方向为逆时针)。利用原坐标点与旋转矩阵相乘,公式如下,x,y为原坐标,a为旋转角度,x\',y\'为旋转后的坐标

  2. 利用近邻插值给旋转后的图像赋上灰度值。由于是根据旋转后的新矩阵坐标映射回原矩阵中的坐标求其灰度值,所以对旋转矩阵求逆矩阵R,原像素位置记为src,中心点记为center1,旋转后像素位置记为dst,中心点记为center2,近邻插值(四舍五入取近似值),整理为以下公式:

                                                       src = round(R * (dst - center2) + center1)
    

若是彩色图则每个通道都如上赋值

双线性插值:其中i,j为当前点的坐标,u为i坐标的偏移量,v为j坐标的偏移量

                                        f(i+u,j+v) = (1-u)(1-v)f(i,j)+u(1-v)f(i+1,j)+(1-u)vf(i,j+1)+ uvf(i+1,j+1)

近邻插值伪代码

function outputimg = myimrotate(A,angle)
% 利用近邻插值法将图像旋转
% 输入:A是读入的图像矩阵,angle是旋转角度(0-360),angle取正为逆时针旋转,取负为顺时针旋转
% 输出:outputimg是输出的图像矩阵

a = 旋转角度/180 * pi 
R = 旋转矩阵
R = 求逆矩阵

[H,W,CH] = 图像的长、宽、通道
%当旋转角度为钝角(顺时针旋转)时加上绝对值
DH = 根据步骤1的公式求出新矩阵的行
DW = 根据步骤1的公式求出新矩阵的行
outputimg = 按照DH和DW新开辟一个矩阵
center1 = 原图像中心坐标
center2 = 新矩阵中心坐标
遍历新矩阵
          dst = 新矩阵中当前点的坐标
          src = 根据步骤3的公式求得当前点对应在原图上的点的坐标
          如果src的坐标点在原图上没有越界)
             outputimg(i,j,:) = 将各个通道对应点在原图的像素值赋给新矩阵
将outputimg类型转换为uint8便于显示图像;
end

双线性插值伪代码

function outputimg = myimrotate_bilinear(A,angle)
% 利用双线性插值法将图像旋转
% A是读入的图像矩阵,angle是旋转角度(0-360),angle取正为逆时针旋转,取负为顺时针旋转
% outputimg是输出的图像矩阵

a = 旋转角度/180 * pi 
R = 旋转矩阵
R = 逆矩阵

[H,W,CH] = 图像的长、宽、通道
%当旋转角度为钝角(顺时针旋转)时加上绝对值
DH = 根据步骤1的公式求出新矩阵的行
DW = 根据步骤1的公式求出新矩阵的行
outputimg = 按照DH和DW新开辟一个矩阵
center1 = 原图像中心坐标
center2 = 新矩阵中心坐标

遍历新矩阵
          dst = 新矩阵中的当前点
          src = 根据步骤3的公式求得当前点对应在原图上的点的坐标(行、列)
          %双线性插值
          a = 对求得的src向下取整
          offset = 计算的src的偏移量
          u = i坐标(行)的偏移量
          v = j坐标(列)的偏移量
          i = 当前点向下取整之后行坐标
          j = 当前点向下取整之后列坐标
          如果i,j,并且(i+1)、(j+1)没有越界
             outputimg(di,dj,:) = 将各个通道对应点根据步骤4公式所求得的在原图上的像素值赋给新矩阵
将outputimg类型转换为uint8便于显示图像
end

近邻插值代码

function outputimg = myimrotate_neighbor(A,angle)
% 利用近邻插值法将图像旋转
% A是读入的图像矩阵,angle是旋转角度
% outputimg是输出的图像矩阵

%角度转换,求旋转矩阵的逆矩阵
a = angle / 180 * pi;
R = [cos(a), -sin(a); sin(a), cos(a)]; %旋转矩阵
R = R\'; %求逆矩阵

%根据原图矩阵生成输出图像所需画布矩阵的大小
[H,W,CH] = size(A);
DH = ceil(H * abs(cos(a)) + W * abs(sin(a)));  %当顺时针旋转时加上绝对值
DW = ceil(H * abs(sin(a)) + W * abs(cos(a)));
outputimg = zeros(DH,DW,CH);
center1 = [H;W] / 2;
center2 = [DH;DW] / 2;

for i = 1:DH
       for j = 1:DW
          dst = [i; j];
          %利用的向量的旋转原理,再与旋转矩阵相乘
          src = round(R * (dst - center2) + center1); %四舍五入近邻插值
          % 逆向进行像素查找
          if (src(1) >= 1 && src(1) <= H && src(2) >= 1 && src(2) <= W)
             outputimg(i,j,:) = A(src(1), src(2),:); 
          end
       end
end
outputimg = uint8(outputimg);
end

实验结果

%调用示例:
A = imread(\'cameraman.tif\');
B = myimrotate_neighbor(A,30);
subplot(1,2,1),imshow(A),title(\'原图\');
subplot(1,2,2),imshow(B),title(\'旋转30°的图像\');

灰度图逆时针30°旋转:

彩色图顺时针30°旋转(等同于逆时针旋转330°):

双线性插值代码

function outputimg = myimrotate_bilinear(A,angle)
% 利用双线性插值法将图像旋转
% A是读入的图像矩阵,angle是旋转角度
% outputimg是输出的图像矩阵


%角度转换,求旋转矩阵的逆矩阵
a = angle / 180 * pi;
R = [cos(a), -sin(a); sin(a), cos(a)];
R = R\'; 

%根据原图矩阵生成输出图像所需画布矩阵的大小
[H,W,CH] = size(A);
DH = floor(H * cos(a) + W * sin(a));  %向上取整
DW = floor(H * sin(a) + W * cos(a));
outputimg = zeros(DH,DW,CH);
center1 = [H;W] / 2;
center2 = [DH;DW] / 2;

for di = 1:DH
       for dj = 1:DW
          dst = [di; dj];
          %利用的向量的旋转原理,再与旋转矩阵相乘
          src = (R * (dst - center2) + center1); 
          %双线性插值
          a = floor(src); %向下取整
          offset = src - a;  %计算的偏移量
          u = offset(1);  %x的偏移量
          v = offset(2);  %y的偏移量
          i = a(1);
          j = a(2);
          % 逆向进行像素查找
          if (src(1) >= 1 && src(1) <= H - 1 && src(2) >= 1 && src(2) <= W - 1)
             outputimg(di,dj,:) = (1-u)*(1-v)*A(i, j, :) + (1 - u) * v * A(i, j + 1, :) + u * (1 - v) * A(i + 1, j, :) + u * v * A(i + 1, j + 1, :); 
          end
       end
end
outputimg = uint8(outputimg);
end
% 调用示例:
A = imread(\'cameraman.tif\');
B = myimrotate_bilinear(A,30);
C = myimrotate_neighbor(A,30);
subplot(1,3,1),imshow(A),title(\'原图\');
subplot(1,3,2),imshow(C),title(\'近邻插值旋转\');
subplot(1,3,3),imshow(B),title(\'双线性插值旋转\');

实验结果

实验分析

  • 映射关系的对应,需要根据旋转后的开辟的新矩阵找在原图中的位置,如下图所示,由原图去给新图像赋像素值的时候,有些坐标映射过来是包含小数,在原图上根本找不到,所以得到部分空点(灰度值=0)
  • 新矩阵的开辟,如上图未根据算法分析步骤1开辟新矩阵,使得旋转后的图像不能完整显示

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Delphi 中文件的操作FileOpen发布时间:2022-07-18
下一篇:
DelphiADOQuery连接数据库的查询、插入、删除、修改发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap