目录
本文章包含以下内容:
代码如下:(可全部放到 function U() 中)
结果示例:
几何运算函数:
旋转
缩放
裁剪
镜像
平移
1、编程实现图像的旋转(imrotate);
2、编程实现图像的按比例缩放(imresize);
3、编程实现图像的裁剪(imcrop)。
4、编程实现图像的镜像变换(水平、垂直和对角镜像);
5、编程实现图像的平移。
function U()
clear;
clc;
%img = imread('cameraman.tif'); % 读取文件
img = imread('peppers.png'); % 读取文件
figure('Name', '原图'); % 开一个标题为“原图”的窗口
imshow(img); % 显示原图
figure('Name', '旋转'); % 开一个标题为“旋转”的窗口
subplot(2,2,1);imshow(xuanzhuan(img, 30));title('旋转 30°');
subplot(2,2,2);imshow(xuanzhuan(img, 90));title('旋转 90°');
subplot(2,2,3);imshow(xuanzhuan(img, -60));title('旋转- 60°');
subplot(2,2,4);imshow(xuanzhuan(img,-180));title('旋转-180°');
figure('Name', '缩放'); % 开一个标题为“缩放”的窗口
subplot(2,2,1);imshow(suofang(img,-1));title('缩放-1(倍数错误提示)');
subplot(2,2,2);imshow(suofang(img,1));title('缩放1.0');
subplot(2,2,3);imshow(suofang(img,0.15));title('缩放0.15');
subplot(2,2,4);imshow(suofang(img,2.7));title('缩放2.7');
figure('Name', '裁剪'); % 开一个标题为“裁剪”的窗口
subplot(2,2,1);imshow(caijian(img,50,80,160,220));title('裁剪,50,80,160,220');
subplot(2,2,2);imshow(caijian(img,-80,10,200,200));title('裁剪,80,1,200,200(负位置错误)');
subplot(2,2,3);imshow(caijian(img,1e4,1e4,1e5,1e5));title('裁剪1e4,1e4,1e5,1e5(超界错误)');
subplot(2,2,4);imshow(caijian(img,200,220,10,100));title('裁剪200,220,10,100(负裁剪区域错误)');
figure('Name', '镜像'); % 开一个标题为“镜像”的窗口
subplot(2,2,1);imshow(jingxiang(img,'x'));title('水平镜像(x)');
subplot(2,2,2);imshow(jingxiang(img,'y'));title('垂直镜像(y)');
subplot(2,2,3);imshow(jingxiang(img,'xy'));title('对角镜像(xy)');
subplot(2,2,4);imshow(jingxiang(img,'z'));title('错误镜像(错误输入)');
figure('Name', '平移'); % 开一个标题为“平移”的窗口
subplot(2,2,1);imshow(pingyi(img,90,60));title('平移90,60°');
subplot(2,2,2);imshow(pingyi(img,60,-190));title('平移60,-190');
subplot(2,2,3);imshow(pingyi(img,-120,-60));title('平移-120,-60');
subplot(2,2,4);imshow(pingyi(img,-180,20));title('平移-180,20');
function img2=xuanzhuan(img,x) % 旋转函数,(图像,角度)
img=im2double(img); % 转double 不然显示会成2值图像
a=size(img); % 得到图像大小
M=a(1);
N=a(2);
cx=cosd(x); % 计算cos(x)
sx=sind(x); % 计算sin(x)
R=[cx,sx,0;-sx,cx,0;0,0,1]; % 旋转矩阵
R_=R'; % 旋转矩阵的逆矩阵
len=[[1,M,1,M];[1,1,N,N];[1,1,1,1]]; % 分别得到图像4个点
len = R * len; % 计算移动后的四角点
x=abs(round(max(len(1,:))-min(len(1,:)))); % 得到旋转后的x大小
y=abs(round(max(len(2,:))-min(len(2,:)))); % 得到旋转后的y大小
if length(a)==3 % 如果是RGB
img2=zeros(x,y,a(3)); % 创建RGB全0矩阵
else
img2=zeros(x,y); % 创建全0矩阵
end
im2=[x/2,y/2,0]; % 旋转后图像中心点,用于旋转前平移
im0=[M/2,N/2,1]; % 原图像中心点,用于旋转后平移
% 如果由原图映射到旋转后图像,会产生空洞,所以由旋转后图像寻找原像素更佳。
% 将旋转后的矩阵平移到原点,逆旋转回去,之后再平移原图像中心点的位置
for i = 1:x
for j = 1:y
a=([i,j,0]-im2)*R_+im0;
% 如果逆变换回去发现点在原图像外,就不赋值。
if (a(1)<=M)&&(a(1)>=0.5)&&(a(2)<=N)&&(a(2)>=0.5)
img2(i,j,:)=img(round(a(1)),round(a(2)),:);
end
end
end
function img2=suofang(img,s) % 缩放函数,(图像,缩放比例(>0))
if s<=0
fprintf('缩放函数比例错误,请使比例>0\n');
img2=img;
return
end
img=im2double(img); % 转double 不然显示会成2值图像
a=size(img); % 得到图像大小
x=round(a(1)*s); % 得到缩放后的x大小
y=round(a(2)*s); % 得到缩放后的y大小
if length(a)==3 % 如果是RGB
img2=zeros(x,y,a(3)); % 创建RGB全0矩阵
else
img2=zeros(x,y); % 创建全0矩阵
end
% 无论缩放比例多少,都是由新图像素点找原图像素点,防止出现空洞。
for i = 1:x
for j = 1:y
M=round(i/s);
N=round(j/s);
if M>0&&N>0&&M<=a(1)&&N<=a(2) % 防止出现索引错误
img2(i,j,:)=img(M,N,:);
end
end
end
function img2=caijian(img,a,b,c,d) % 裁剪函数,(图像,裁剪后大小)
if a<=1||b<=1||c<=1||d<=1
fprintf('裁剪大小错误,裁剪位置应>=1\n');
img2=img;
return
end
img=im2double(img); % 转double 不然显示会成2值图像
s=size(img); % 得到图像大小
if a>=s(1)||b>=s(2)||c>=s(1)||d>=s(2)
fprintf('裁剪大小错误,裁剪位置应<=图像边界大小\n');
img2=img;
return
end
x=c-a+1; % 得到裁剪后的x大小
y=d-b+1; % 得到裁剪后的y大小
if x<1||y<1
fprintf('裁剪大小错误,裁剪位置应a<=c,b<=d\n');
img2=img;
return
end
img2=img(a:c,b:d,:);
function img2=jingxiang(img,x) % 镜像函数,(图像,变换类型('x','y','xy'))
img=im2double(img); % 转double 不然显示会成2值图像
a=size(img); % 得到图像大小
switch x % 根据x不同,进行不同的变换
case 'y'
img2(1:a(1),1:a(2),:)=img(a(1):-1:1,1:a(2),:);
case 'x'
img2(1:a(1),1:a(2),:)=img(1:a(1),a(2):-1:1,:);
case 'xy'
img2(1:a(1),1:a(2),:)=img(a(1):-1:1,a(2):-1:1,:);
otherwise
fprintf('不是字符x,y,或xy,请检查输入');
img2=img;
end
function img2=pingyi(img,y,x) % 平移函数,(图像,x平移距离,y平移距离)
img=im2double(img); % 转double 不然显示会成2值图像
a=size(img); % 得到图像大小
if length(a)==3 % 如果是RGB
img2=zeros(a(1)+abs(x),a(2)+abs(y),a(3)); % 创建RGB全0矩阵
else
img2=zeros(a(1)+abs(x),a(2)+abs(y)); % 创建全0矩阵
end
for i=1:a(1)
for j=1:a(2)
if(x<0 && y<0)
img2(i,j,:)=img(i,j,:); %如果进行左上移动,对新图像矩阵进行赋值
elseif(x>0 && y>0)
img2(i+x,j+y,:)=img(i,j,:); %如果进行右下移动,对新图像矩阵进行赋值
elseif(x>0 && y<0)
img2(i+x,j,:)=img(i,j,:); %如果进行右上移动,对新图像矩阵进行赋值
else
img2(i,j+y,:)=img(i,j,:); %如果进行左下移动,对新图像矩阵进行赋值
end
end
end
缩放函数比例错误,请使比例>0
裁剪大小错误,裁剪位置应>=1
裁剪大小错误,裁剪位置应<=图像边界大小
裁剪大小错误,裁剪位置应a<=c,b<=d
不是字符x,y,或xy,请检查输入>>
function img2=xuanzhuan(img,x) % 旋转函数,(图像,角度)
img=im2double(img); % 转double 不然显示会成2值图像
a=size(img); % 得到图像大小
M=a(1);
N=a(2);
cx=cosd(x); % 计算cos(x)
sx=sind(x); % 计算sin(x)
R=[cx,sx,0;-sx,cx,0;0,0,1]; % 旋转矩阵
R_=R'; % 旋转矩阵的逆矩阵
len=[[1,M,1,M];[1,1,N,N];[1,1,1,1]]; % 分别得到图像4个点
len = R * len; % 计算移动后的四角点
x=abs(round(max(len(1,:))-min(len(1,:)))); % 得到旋转后的x大小
y=abs(round(max(len(2,:))-min(len(2,:)))); % 得到旋转后的y大小
if length(a)==3 % 如果是RGB
img2=zeros(x,y,a(3)); % 创建RGB全0矩阵
else
img2=zeros(x,y); % 创建全0矩阵
end
im2=[x/2,y/2,0]; % 旋转后图像中心点,用于旋转前平移
im0=[M/2,N/2,1]; % 原图像中心点,用于旋转后平移
% 如果由原图映射到旋转后图像,会产生空洞,所以由旋转后图像寻找原像素更佳。
% 将旋转后的矩阵平移到原点,逆旋转回去,之后再平移原图像中心点的位置
for i = 1:x
for j = 1:y
a=([i,j,0]-im2)*R_+im0;
% 如果逆变换回去发现点在原图像外,就不赋值。
if (a(1)<=M)&&(a(1)>=0.5)&&(a(2)<=N)&&(a(2)>=0.5)
img2(i,j,:)=img(round(a(1)),round(a(2)),:);
end
end
end
function img2=suofang(img,s) % 缩放函数,(图像,缩放比例(>0))
if s<=0
fprintf('缩放函数比例错误,请使比例>0\n');
img2=img;
return
end
img=im2double(img); % 转double 不然显示会成2值图像
a=size(img); % 得到图像大小
x=round(a(1)*s); % 得到缩放后的x大小
y=round(a(2)*s); % 得到缩放后的y大小
if length(a)==3 % 如果是RGB
img2=zeros(x,y,a(3)); % 创建RGB全0矩阵
else
img2=zeros(x,y); % 创建全0矩阵
end
% 无论缩放比例多少,都是由新图像素点找原图像素点,防止出现空洞。
for i = 1:x
for j = 1:y
M=round(i/s);
N=round(j/s);
if M>0&&N>0&&M<=a(1)&&N<=a(2) % 防止出现索引错误
img2(i,j,:)=img(M,N,:);
end
end
end
function img2=caijian(img,a,b,c,d) % 裁剪函数,(图像,裁剪后大小)
if a<=1||b<=1||c<=1||d<=1
fprintf('裁剪大小错误,裁剪位置应>=1\n');
img2=img;
return
end
img=im2double(img); % 转double 不然显示会成2值图像
s=size(img); % 得到图像大小
if a>=s(1)||b>=s(2)||c>=s(1)||d>=s(2)
fprintf('裁剪大小错误,裁剪位置应<=图像边界大小\n');
img2=img;
return
end
x=c-a+1; % 得到裁剪后的x大小
y=d-b+1; % 得到裁剪后的y大小
if x<1||y<1
fprintf('裁剪大小错误,裁剪位置应a<=c,b<=d\n');
img2=img;
return
end
img2=img(a:c,b:d,:);
function img2=jingxiang(img,x) % 镜像函数,(图像,变换类型('x','y','xy'))
img=im2double(img); % 转double 不然显示会成2值图像
a=size(img); % 得到图像大小
switch x % 根据x不同,进行不同的变换
case 'y'
img2(1:a(1),1:a(2),:)=img(a(1):-1:1,1:a(2),:);
case 'x'
img2(1:a(1),1:a(2),:)=img(1:a(1),a(2):-1:1,:);
case 'xy'
img2(1:a(1),1:a(2),:)=img(a(1):-1:1,a(2):-1:1,:);
otherwise
fprintf('不是字符x,y,或xy,请检查输入');
img2=img;
end
function img2=pingyi(img,y,x) % 平移函数,(图像,x平移距离,y平移距离)
img=im2double(img); % 转double 不然显示会成2值图像
a=size(img); % 得到图像大小
if length(a)==3 % 如果是RGB
img2=zeros(a(1)+abs(x),a(2)+abs(y),a(3)); % 创建RGB全0矩阵
else
img2=zeros(a(1)+abs(x),a(2)+abs(y)); % 创建全0矩阵
end
for i=1:a(1)
for j=1:a(2)
if(x<0 && y<0)
img2(i,j,:)=img(i,j,:); %如果进行左上移动,对新图像矩阵进行赋值
elseif(x>0 && y>0)
img2(i+x,j+y,:)=img(i,j,:); %如果进行右下移动,对新图像矩阵进行赋值
elseif(x>0 && y<0)
img2(i+x,j,:)=img(i,j,:); %如果进行右上移动,对新图像矩阵进行赋值
else
img2(i,j+y,:)=img(i,j,:); %如果进行左下移动,对新图像矩阵进行赋值
end
end
end