MATLAB 利用旋转矩阵来编写一个旋转图像的函数 只要对就再追加100分

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MATLAB 利用旋转矩阵来编写一个旋转图像的函数 只要对就再追加100分相关的知识,希望对你有一定的参考价值。

利用旋转矩阵R=[cosx, -sinx; sinx cosx]写一个函数 I2=myrotate(I1,theta) 运行之后读入I1并转theta度 把新图存入I2。
我打算用这个函数
function g = myrotate(F,a) % F代表图像,a代表旋转角度
[m,n] = size(F);
figure
imshow(F);
g=double(F);F=[];
for i=1:m
for j=1:n
i1=round(i*cos(a) - j*sin(a)+ n * sin(a))+1;
j1=round(i*sin(a) + j*cos(a));
F(i1,j1)=g(i,j);
end
end
figure
imshow(uint8(F))
这个函数可以实现一部分,但是很奇怪的是角度a的设定有些问题,比如我如果设a=90,就会出现
??? Attempted to access F(286,0); index must be a positive integer or logical.

Error in ==> whirl1 at 10
F(i1,j1)=g(i,j);
设为pi/2就可以,可以告诉我问题出在哪里了吗?

非常感谢!

如果按照你的程序的话,根据提示内容,在计算
i1=round(i*cos(a) - j*sin(a)+ n * sin(a))+1;
j1=round(i*sin(a) + j*cos(a));

这两个时会出现零值,那么,在MATLAB中索引F矩阵就是错误的了,你可以设置断点,然后单步运行一下看看在哪一步出现的零值,你根据旋转矩阵的计算应该是没有问题的,关键是灰度映射时可能出现零位置,最好在其中加入判断的语句,j1计算会出现0值。

你这样写,是沿坐标轴原点旋转,你说的我原来写的那个是沿固定点旋转,实现都是使用旋转矩阵,沿固定点只是先平移到原点,然后再平移回去,你可以看看,具体的我已经记不太清楚了,呵呵,已经不做图像了。

我写的那个的程序:

function im_final = imrotate_my(im_path,theta,options)
% IM_ROTATE 两维图像旋转以及双线性灰度插值算法的实现
% im_path 图像存储路径
% theta 旋转角度,正数表示顺时针旋转
% options 可以为circular(超出范围部分,按照周期形式扩展)
% crop(超出部分置零,即全黑)
% Ref. 章毓晋. 图像工程(上册)——图像处理. 清华大学出版社
% Author: lskyp Date: 2009.08.12
% Version: V1.2 Original Version: V1.0 im_bilinear.m;im_rotate.m
% with the parameter options added

error(nargchk(2,3,nargin,'string'))

if nargin == 2
options = 'circular';
else
if ~ (strcmp(options,'circular') || strcmp(options,'crop'))
error('错误的输出方法')
end
end

im_init = imread(im_path);
im_init = double(im_init);
im_height = size(im_init,1);
im_width = size(im_init,2);
% 分别处理灰度图像和RGB图像
if ndims(im_init) == 3
im_final = zeros(im_height,im_width,3);
R = im_init(:,:,1);
G = im_init(:,:,2);
B = im_init(:,:,3);
R_final = im_final(:,:,1);
G_final = im_final(:,:,2);
B_final = im_final(:,:,3);
else
im_final = zeros(im_height,im_width);
end

rot_matrix = [cos(theta) -sin(theta);sin(theta) cos(theta)];
orig_h = (im_height + 1)/2;
orig_w = (im_width + 1)/2;
for h = 1:im_height
for w = 1:im_width
% 平移至原点,旋转,然后再平移回去
new_position = rot_matrix*[h - orig_h;w - orig_w] + [orig_h;orig_w];

% 超出范围按周期扩展控制,options参数控制
if strcmp(options,'circular')
new_position(1) = mod(new_position(1),im_height);
new_position(2) = mod(new_position(2),im_width);
if new_position(1) == 0
new_position(1) = im_height;
end
if new_position(2) == 0
new_position(2) = im_width;
end
end

% 如果新位置为整数,那么直接赋予灰度值或者RGB值,否则,按照双线性插值计算。
% 使用后向映射
if new_position == round(new_position)
if new_position(1) == 0
new_position(1) = 1;
end
if new_position(2) == 0
new_position(2) = 1;
end
% 超出范围控制,options为crop选项,超出范围置零
if strcmp(options,'crop') && (new_position(1) >= im_height || ...
new_position(2) >= im_width || new_position(1) < 0 || ...
new_position(2) < 0)
if ndims(im_init) == 3
R_final(h,w) = 0;
G_final(h,w) = 0;
B_final(h,w) = 0;
else
im_final(h,w) = 0;
end
else
if ndims(im_init) == 3
R_final(h,w) = R(new_position(1),new_position(2));
G_final(h,w) = G(new_position(1),new_position(2));
B_final(h,w) = B(new_position(1),new_position(2));
else
im_final(h,w) = im_init(new_position(1),new_position(2));
end
end
else
h_new = floor(new_position(1));
w_new = floor(new_position(2));
if h_new == 0
h_new = 1;
end
if w_new == 0
w_new = 1;
end

% 超出范围控制,options为crop选项,超出范围置零
if strcmp(options,'crop') && (h_new >= im_height || ...
w_new >= im_width || h_new < 0 || ...
w_new < 0)
if ndims(im_init) == 3
R_final(h,w) = 0;
G_final(h,w) = 0;
B_final(h,w) = 0;
else
im_final(h,w) = 0;
end
else
% 边界控制
h1 = h_new + 1;
w1 = w_new + 1;
if h1 >= im_height + 1
h1 = mod(h1,im_height);
end
if w1 >= im_width + 1
w1 = mod(w1,im_width);
end
if ndims(im_init) == 3
% 双线性插值的实现过程
% Ref. 章毓晋. 图像工程(上册)——图像处理. 清华大学出版社
R_temp1 = R(h1,w_new)*(new_position(1) - h_new) + ...
R(h_new,w_new)*(h_new + 1 - new_position(1));
R_temp2 = R(h1,w1)*(new_position(1) - h_new) + ...
R(h_new,w1)*(h_new + 1 - new_position(1));
R_final(h,w) = R_temp1*(w_new + 1 - new_position(2)) + ...
R_temp2*(new_position(2) - w_new);
G_temp1 = G(h1,w_new)*(new_position(1) - h_new) + ...
G(h_new,w_new)*(h_new + 1 - new_position(1));
G_temp2 = G(h1,w1)*(new_position(1) - h_new) + ...
G(h_new,w1)*(h_new + 1 - new_position(1));
G_final(h,w) = G_temp1*(w_new + 1 - new_position(2)) + ...
G_temp2*(new_position(2) - w_new);
B_temp1 = B(h1,w_new)*(new_position(1) - h_new) + ...
B(h_new,w_new)*(h_new + 1 - new_position(1));
B_temp2 = B(h1,w1)*(new_position(1) - h_new) + ...
B(h_new,w1)*(h_new + 1 - new_position(1));
B_final(h,w) = B_temp1*(w_new + 1 - new_position(2)) + ...
B_temp2*(new_position(2) - w_new);
else
gray_temp1 = im_init(h1,w_new)*(new_position(1) - h_new) + ...
im_init(h_new,w_new)*(h_new + 1 - new_position(1));
gray_temp2 = im_init(h1,w1)*(new_position(1) - h_new) + ...
im_init(h_new,w1)*(h_new + 1 - new_position(1));
im_final(h,w) = gray_temp1*(w_new + 1 - new_position(2)) + ...
gray_temp2*(new_position(2) - w_new);
end
end
end
end
end
if ndims(im_init) == 3
im_final(:,:,1) = R_final;
im_final(:,:,2) = G_final;
im_final(:,:,3) = B_final;
end
im_final = im2uint8(mat2gray(im_final));

实现部分主要就在控制边界那个地方,我用的周期扩展,如果为零则认为是边界地方,实现部分你可以看看。

具体的就只有这么多了,呵呵,多谢信任。

声明一下,程序内容如有朋友转,请注明。

这个函数只能帮助理解算法,如果真正用起来,还是使用IPT的imrotate函数。
参考技术A 希望对你有用,http://zhidao.baidu.com/question/123410453.html?si=8

当然建议使用imrotate,其中有三种差值方法供使用,理论上效果更好;并且可以设置输出图像的尺寸大小~~
参考技术B %图像旋转
%X,Y为其行列数
Image=imread('test.png');
Image=rgb2gray(Image);
angle=30;
%角度任意的一个数 表示30度
pai=3.14;
Angle=pai*angle/180;
%转换一下角度的表示方法。
[X,Y]=size(Image);

%原图显示
subplot(2,1,1);
imshow(Image);
title('原图像');

%计算四个角点的新坐标,确定旋转后的显示区域
LeftTop(1,1)=-(Y-1)*sin(Angle);
LeftTop(1,2)=(Y-1)*cos(Angle);

LeftBottom(1,1)=0;
LeftBottom(1,2)=0;

RightTop(1,1)=(X-1)*cos(Angle)-(Y-1)*sin(Angle);
RightTop(1,2)=(X-1)*sin(Angle)+(Y-1)*cos(Angle);

RightBottom(1,1)=(X-1)*cos(Angle);
RightBottom(1,2)=(X-1)*sin(Angle);

%计算显示区域的行列数
Xnew=max([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)])-min([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)]);
Ynew=max([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)])-min([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)]);

% 分配新显示区域矩阵
ImageNew=zeros(round(Xnew),round(Ynew))+255;

%计算原图像各像素的新坐标
for indexX=0:(X-1)
for indexY=0:(Y-1)
ImageNew(round(indexX*cos(Angle)-indexY*sin(Angle))+round(abs(min([LeftTop(1,1),LeftBottom(1,1),RightTop(1,1),RightBottom(1,1)])))+1,1+round(indexX*sin(Angle)+indexY*cos(Angle))+round(abs(min([LeftTop(1,2),LeftBottom(1,2),RightTop(1,2),RightBottom(1,2)]))))=Image(indexX+1,indexY+1);
end
end

%显示
subplot(2,1,2);
imshow((ImageNew)/255)
promp=['旋转角度为:' int2str(angle) '的图像']
title(promp);

%储存
imwrite(ImageNew,'new.png','png'); %%%图片存储 有点问题,过年了来不及看了,你自己调下
参考技术C image processing toolbox 工具包。 参考技术D 因为你用的cos函数 所以必须使用弧度制角度,使用cosd函数就可以直接使用角度了

Matlab 图像平移旋转缩放镜像

今天学习了用Matlab实现对图像的基本操作。在Matlab中,图像是按照二维矩阵的形式表示的。所以对图像的操作就是对矩阵的操作。 

对图像进行缩放、平移、旋转,都可以转化为矩阵的运算。 
关于变换矩阵的构造,请参考: 
《 [gym 101047C Robotics Competition] 矩阵快速幂求解点旋转平移N次之后的位置》 
参考原图: 
技术分享图片

1. 图像平移

init = imread(‘Fig3.tif‘); % 读取图像
[R, C] = size(init); % 获取图像大小
res = zeros(R, C); % 构造结果矩阵。每个像素点默认初始化为0(黑色)
delX = 50; % 平移量X
delY = 50; % 平移量Y
tras = [1 0 delX; 0 1 delY; 0 0 1]; % 平移的变换矩阵 

for i = 1 : R
    for j = 1 : C
        temp = [i; j; 1];
        temp = tras * temp; % 矩阵乘法
        x = temp(1, 1);
        y = temp(2, 1);
        % 变换后的位置判断是否越界
        if (x <= R) & (y <= C) & (x >= 1) & (y >= 1)
            res(x, y) = init(i, j);
        end
    end
end;

imshow(uint8(res)); % 显示图像

技术分享图片

2. 图像旋转

init = imread(‘Fig3.tif‘); % 读取图像
[R, C] = size(init); % 获取图像大小
res = zeros( R,  C); % 构造结果矩阵。每个像素点默认初始化为0(黑色)

alfa = -15 * 3.1415926 / 180.0; % 旋转角度
tras = [cos(alfa) -sin(alfa) 0; sin(alfa) cos(alfa) 0; 0 0 1]; % 旋转的变换矩阵

for i = 1 : R
    for j = 1 : C
        temp = [i; j; 1];
        temp = tras * temp;% 矩阵乘法
        x = uint16(temp(1, 1));
        y = uint16(temp(2, 1));
        % 变换后的位置判断是否越界
        if (x <= R) & (y <= C) & (x >= 1) & (y >= 1)
            res(i, j) = init(x, y);
        end
    end
end;

imshow(uint8(res));  % 显示图像

技术分享图片

3. 图像缩放

init = imread(‘Fig3.tif‘); % 读取图像
[R, C] = size(init); % 获取图像大小
timesX = 3; % X轴缩放量
timesY = 3; % Y轴缩放量
res = zeros(timesX * R, timesY * C); % 构造结果矩阵。每个像素点默认初始化为0(黑色)
tras = [1/timesX 0 0; 0 1/timesY 0; 0 0 1]; % 缩放的变换矩阵 

for i = 1 : timesX * R
    for j = 1 : timesY * C
        temp = [i; j; 1];
        temp = tras * temp; % 矩阵乘法
        x = uint8(temp(1, 1));
        y = uint8(temp(2, 1));
        % 变换后的位置判断是否越界
        if (x <= R) & (y <= C) & (x >= 1) & (y >= 1)
            res(i, j) = init(x, y);
        end
    end
end;

imshow(uint8(res)); % 显示图像

技术分享图片

4. 图像镜像(水平)

init = imread(‘Fig3.tif‘);
[R, C] = size(init);
res = zeros(R, C);

for i = 1 : R
    for j = 1 : C
        x = i;
        y = C - j + 1;
        res(x, y) = init(i, j);
    end
end

imshow(uint8(res));

技术分享图片





以上是关于MATLAB 利用旋转矩阵来编写一个旋转图像的函数 只要对就再追加100分的主要内容,如果未能解决你的问题,请参考以下文章

matlab中图像旋转

matlab中figure的图像旋转

Matlab 图像平移旋转缩放镜像

Matlab 图像平移旋转缩放镜像

如何在matlab中进行数据的平移和旋转

给定一个 n × n 的二维矩阵表示一个图像, 将图像顺时针旋转 90 度js实现