数字图像处理技术与应用练习题

说明:不允许直接使用MATLAB(或者OPENCV等)所带的图像处理函数,重点考察大家是否理解了各种处理算法,算法可用伪代码描述。算法应较详细。

原文章:

数字图像处理技术与应用练习题_decadeheart的博客-CSDN博客_数字图像处理图像缩放计算题

图像的几何变换
图像放大缩小
设一幅大小为M×N的灰度图像I中,现要变成(放大或缩小)为 P×Q的图像J,请写出J的生成算法(要求使用双线性插值)。

在这里插入图片描述

 

算法思路:
在数学上,双线性插值是有两个变量的插值函数的线性插值扩展,其核心思想是在X和Y两个方向分别进行一次线性插值。如果选择一个坐标系统使得 的四个已知点坐标分别为 (0, 0)、(0, 1)、(1, 0) 和 (1, 1),那么插值公式就可以化简。

用矩阵运算来表示的话就是:

在这里插入图片描述
图像的空间变换,也称几何变换或几何运算,包括图像的平移、旋转、镜像变换、转置、缩放等。空间变换可如下表示:设(u,v)为源图像上的点,(x,y)为目标图像上的点,则空间变换就是将源图像上(u,v)处的颜色值与目标图像上(x,y)处的颜色对应起来。

 

计算机所处理的图像都是指点阵图,也就是用一个像素矩阵来描述一副图像。 举个简单的图像:3X3 的256级灰度图,也就是高为3个象素,宽也是3个象素的图像,每个象素的取值可以是 0-255,代表该像素的亮度,255代表最亮,也就是白色,0代表最暗,即黑色 。

假如图像的象素矩阵如下所示:(这个矩阵中,图象处理中最常用的坐标系是:x从左到右,从0开始,y从上到下,也是从0开始)
234 38 22
67 44 12
89 65 63
如果想把这副图放大为 4X4大小的图像,那么第一步肯定想到的是先把4X4的矩阵先画出来再说,好了矩阵画出来了,如下所示,当然,矩阵的每个像素都是未知数,等待着我们去填充:
? ? ? ?
? ? ? ?
? ? ? ?
? ? ? ?
然后要往这个空的矩阵里面填值了,要填的值从哪里来来呢?是从源图中来,好,先填写目标图最左上角的象素,坐标为(0,0),那么该坐标对应源图中的坐标可以由如下公式得出:

srcX = dstX * (srcWidth / dstWidth)
srcY = dstY * (srcHeight / dstHeight)

套用公式,就可以找到对应的原图的坐标了
(0*(3/4),0*(3/4))=>(00.75,00.75)=>(0,0)

找到了源图的对应坐标,就可以把源图中坐标为(0,0)处的234象素值填进去目标图的(0,0)这个位置了。
接下来,如法炮制,寻找目标图中坐标为(1,0)的象素对应源图中的坐标,套用公式:

(10.75,00.75)=>(0.75,0)

结果发现,得到的坐标里面竟然有小数,这可怎么办?计算机里的图像可是数字图像,象素就是最小单位了,象素的坐标都是整数,从来没有小数坐标。这时候采用的一种策略就是采用四舍五入的方法(也可以采用直接舍掉小数位的方法),把非整数坐标转换成整数,好,那么按照四舍五入的方法就得到坐标(1,0),完整的运算过程就是这样的:

(10.75,00.75)=>(0.75,0)=>(1,0)

那么就可以再填一个象素到目标矩阵中了,同样是把源图中坐标为(1,0)处的像素值38填入目标图中的坐标。

依次填完每个象素,一幅放大后的图像就诞生了,像素矩阵如下所示:

234 38 22 22
67 44 12 12
89 65 63 63
89 65 63 63

这种放大图像的方法叫做最临近插值算法,这是一种最基本、最简单的图像缩放算法,效果也是最不好的,放大后的图像有很严重的马赛克,缩小后的图像有很严重的失真;效果不好的根源就是其简单的最临近插值方法引入了严重的图像失真,比如,当由目标图的坐标反推得到的源图的的坐标是一个浮点数的时候,采用了四舍五入的方法,直接采用了和这个浮点数最接近的象素的值,这种方法是很不科学的,当推得坐标值为 0.75的时候,不应该就简单的取为1,既然是0.75,比1要小0.25 ,比0要大0.75 ,那么目标象素值其实应该根据这个源图中虚拟的点四周的四个真实的点来按照一定的规律计算出来的,这样才能达到更好的缩放效果。

双线型内插值算法就是一种比较好的图像缩放算法,它充分的利用了源图中虚拟点四周的四个真实存在的像素值来共同决定目标图中的一个像素值,因此缩放效果比简单的最邻近插值要好很多,计算量比零阶插值大,但缩放后图像质量高,不会出现像素值不连续的情况。

双线性内插值算法描述如下:
对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v) (其中i、j均为浮点坐标的整数部分,u、v为浮点坐标的小数部分,是取值[0,1)区间的浮点数),则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
其中f(i,j)表示源图像(i,j)处的的像素值,以此类推。

假如目标图的象素坐标为(1,1),那么反推得到的对应于源图的坐标是(0.75 , 0.75), 这其实只是一个概念上的虚拟象素,实际在源图中并不存在这样一个象素,那么目标图的象素(1,1)的取值不能够由这个虚拟象素来决定,而只能由源图的这四个象素共同决定:(0,0)(0,1)(1,0)(1,1),而由于(0.75,0.75)离(1,1)要更近一些,那么(1,1)所起的决定作用更大一些,这从公式1中的系数uv=0.75×0.75就可以体现出来,而(0.75,0.75)离(0,0)最远,所以(0,0)所起的决定作用就要小一些,公式中系数为(1-u)(1-v)=0.25×0.25也体现出了这一特点;

算法具体步骤如下:

假设原始图像大小为size=m×n,其中m与n分别是原始图像的行数与列数。若图像的缩放因子是t(t>0),则目标图像的大小size=t×m×t×n。对于目标图像的某个像素点P(x,y)通过P*1/t可得到对应的原始图像坐标P’( x1,y1),其中x1=x/t,y1=y/t,由于x1,y1都不是整数所以并不存在这样的点,这样可以找出与它相邻的四个点的灰度f1、f2、f3、f4,使用双线性插值算法就可以得到这个像素点P’(x1,y1)的灰度,也就是像素点P(x,y)的灰度。
一个完整的双线性插值算法可描述如下:

(1)通过原始图像和比例因子得到新图像的大小,并创建新图像。
(2)由新图像的某个像素(x,y)映射到原始图像(x’,y’)处。
(3)对x’,y’向下取整得到(xx,yy)并得到(xx,yy)、(xx+1,yy)、(xx,yy+1)和(xx+1,yy+1)的值。
(4)利用双线性插值计算公式得到像素点(x,y)的值并写回新图像。
(5)重复步骤(2)直到新图像的所有像素写完。

图像旋转
设一幅大小为M×N的灰度图像I中,现要将其逆时针旋转 A度,得到图像J,请写出J的生成算法(要求使用近邻插值)。
旋转变换,可以看成是在一个橡皮膜上印刷一副图像,然后根据预定的一组规则拉伸该薄膜,包括两个基本操作:(1)坐标的空间变换(2)灰度内插,即对空间变换后的像素赋灰度值。此处采用近邻插值法,将图像中近邻的灰度赋给每个新的位置。
坐标变换可由下式表示:


其中(v,w)是原图像中像素的坐标,(x,y)是变换后图像像素的坐标。用于旋转变换的空间坐标变换如下:

在这里插入图片描述
而数学坐标系和图像坐标系不
同,当对图像进行旋转时,图像以自身中心为 原点建立坐标系,即数学坐标系,图像坐标系确是以图像左上角为原点,则 需要进行坐标系的变换。总体的变换步骤为:
(1)先将原图的图像坐标系转换为数学坐标系,变换如公式②,(2)在数学坐 标系下使用旋 转坐标变换矩阵①进行旋转计算(3)将旋转后的图像的数 学坐标转回图像 坐 标,变换如公式③。

 

在这里插入图片描述

 

在这里插入图片描述

 

其中,m表示宽,n表示高,m’表示旋转后图像宽,n’表示旋转后图像高。
最终的公式变换如下:

在这里插入图片描述
坐标变换后,扫描图像,对于图像中灰度为0的点按照近邻插值法进行赋值。

代码如下:

im1=imread('user.png');
[m,n,p]=size(im1);

a=0.5;
%a=sin30=0.5
b=0.866; 
%b=cos30=0.866
 

row=n*a+m*b;
col=n*b+m*a;
for i=1:row
    for j=1:col
        %对新坐标赋0值
        im2(i,j,:)=uint8(0);
    end
end
for i=1:m
for j=1:n
%根据公式计算新坐标
        x_=round(abs((i-m/2)*b-(j-n/2)*a+row/2));
        y_=round(abs((i-m/2)*a+(j-n/2)*b+col/2));
        for k=1:3
            im2(x_,y_,k)=im1(i,j,k);
        end
    end
end
temp1=uint8(0);
temp2=uint8(0);
temp3=uint8(0);
for i=1:row
    
    temp1=uint8(0);
    temp2=uint8(0);
    temp3=uint8(0);
    for j=1:col
        
        if(im2(i,j,:)==uint8(0))
        else
            kk=j;
        end
    end
    for j=1:kk
        if(im2(i,j,:)==uint8(0))
            im2(i,j,1)=temp1;
            im2(i,j,2)=temp2;
            im2(i,j,3)=temp3;
        else
           temp1=im2(i,j,1);
           temp2=im2(i,j,2);
           temp3=im2(i,j,3);
        end
    end
end
imshow(im1);
figure;
imwrite(im1,'5.png');
imshow(im2);

imwrite(im2,'6.png');


最终效果如下图:

在这里插入图片描述

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值