图像的基本操作

这是第一次用matlab做数字图像处理实验,话不多说,直接上实验。

题目:

1、读入一幅RGB图像,变换为灰度图像和二值图像,并在同一个窗口内分别显示RGB图像和灰度图像,注上文字标题,并将结果以文件形式存到磁盘上。

2、对图像执行放大、缩小及旋转操作,分别采用最近邻插值、双线性插值及双三次插值方法实现,要求根据算法自己编写代码实现,并分析三种方法的优缺点。



下面将实验分为6个小实验:

一、读入一幅RGB图像,变换为灰度图像,并在同一个窗口内分别显示RGB图像和灰度图像,注上文字标题,并将结果以文件形式存到磁盘上

实验原理:

由于此题重点在于怎么实现rgb2gray()函数算法,所以这里主要描述这块,关于图片读取等简单的操作不做过多分析。那么根据官方帮助文档中对rgb2gray()函数算法的描述可知、图像灰度是由R、G、B三个分量加权和得到的,加权公式为:0.2989R + 0.5870G + 0.1140*B,那么可以分别将每个像素的R、G、B三个分量分别读取出来再分别加权即可。当然,加权得到的灰度值存放在一个和原图大小一样的矩阵中,最后再用uint8()函数将矩阵转化为8位的无符号整型以便图像显示输出。输出前使用imwrite()函数写入到指定文件夹,最后使用figure()、suplot()、imshow()进行输出展示,使用title()函数给图像加上标题。



二、读入一幅RGB图像,变换为二值图像,并在同一个窗口内分别显示RGB图像和二值图像,注上文字标题,并将结果以文件形式存到磁盘上。

实验原理:

同样这里也只重点介绍本实验关键部分,即Imbinarize()函数的算法原理。首先Imbinarize()算法思想是在灰度图像中,将高于阈值的值替换为1,反之替换为0,这里的阈值是通过计算前景色和背景色的类间方差,当类间方差(Ostu算法)越大时,说明图像分割得越好,最大时效果最佳,对应的灰度值即为阈值。最后通过对每个像素置0或者置1操作,得到二值图像。输出前使用imwrite()函数写入到指定文件夹,最后使用figure()、suplot()、imshow()进行输出展示,使用title()函数给图像加上标题。
下面来介绍imbinarize()算法的关键环节,即阈值的计算,这里采用Ostu算法
Ostu算法思想:在一个灰度图像中,取一个阈值,将值大于阈值的划为前景色、反之划为背景色,然后计算它们的类间方差,然后不断地进行循环比较,取类间方差最大时所对应的阈值即为最优阈值。下面是类间方差的计算公式:

   bcv = nuPixRa_A * (avPixValue_A-avPixValue)^2

     +nuPixRa_B*(avPixValue_B-avPixValue)^2;

bcv:类间方差值         avPixValue总的像素平均灰度值

nuPixRa_A:前景色像素数量占比  nuPixRa_B:背景色像素数量占比

avPixValue_A:前景色像素平均灰度 avPixValue_B:背景色像素平均灰度值



三、用最邻近插值算法实现图像的放大和缩小

实验原理:

同样这里也只重点介绍本实验关键部分,即最邻近插值的算法原理。由于放大和缩小操作的原理一样,所以这里在一个程序中即可实现。同样,对于原理,这里以图像的放大操作为例(缩小操作同样如此),最邻近插值算法主要考虑的是放大后的图像中每个像素与原图中每个像素的对应关系,分别设srcX、srcY、dstX、dstY、srcW、srcH、dstW、dstH,进而根据缩放比例关系可得以下公式:
在这里插入图片描述

但是这个公式在实际对应中会发生向偏移现象,因为图像中左下角、右下角的像素没有参与计算且每个目标像素值偏左上,因此,为了减小这种误差,本次实验采用下面这个改进公式,使得目标图像和原图像中心对齐:
在这里插入图片描述

那么通过这个公式就找到了目标图像每个像素点与原图像每个的对应关系,由于计算出来的srcX、srcY很可能为小数,那么就取离(srcX,srcY)这个这个点最近的像素灰度值为当前目标图像的像素灰度值即可,通过循环遍历即可将目标图像所有像素的灰度值计算出来。最后使用figure()、suplot()、imshow()进行输出展示,使用title()函数给图像加上标题。

边界处理:

当然这里在算srcX、srcY时,由于取离该点最近的像素点时用的是round()函数,可能会使得srcX或者srcY变为0或者-1或者超出最长度而越界,所以这里要对这种边界进行判断处理。对于srcX或者srcY变为0或者超出最长度的情况来说,即让srcX和srcY至少为1。对于srcX或者srcY变为-1的情况来说,让原图的灰度矩阵在缩小、放大操作以前,在其外围向外扩展一个像素。



四、用双线性插值算法实现图像的放大和缩小

实验原理:

双线性插值法和前面的最邻近插值法大体类似,区别在于当最邻近插值法找到对应的原图像坐标点时,会根据坐标取最近的像素的灰度值,而双线性插值法则会根据其离周围4个像素点的距离来加权计算得到新的灰度值,所以这里就不再赘述双线性插值法和最邻近插值法相同的部分,而是描述新像素的灰度值加权计算公式。例如下图情况:
在这里插入图片描述

其中,点坐标为:Q11 = (x1, y1)、Q12 = (x1, y2)、Q21 = (x2, y1) 、Q22 = (x2, y2)
首先根据坐标在X方向上进行一次插值,计算出R1、R2点的值,得到:
在这里插入图片描述
然后再在Y方向上进行一次插值,计算P点的值,得到:
在这里插入图片描述

整理可得:
在这里插入图片描述

由于双线性插值每次使用的都是相邻的四个像素点,所以,(x2-x1)(y2-y1)=1恒成立,化简可得:
在这里插入图片描述

由于P点坐标会出现小数的情况,因此可以分别用u和v分别表示其横纵坐标的小数部分,用i和j分别表示其横纵坐标的整数部分因此上式可化为:
在这里插入图片描述

因此,只需要对新图像中的每个每个像素点找到其对应原图像素点的对应关系,再运用上式即可得到缩小或放大的图像。最后使用figure()、suplot()、imshow()进行输出展示,使用title()函数给图像加上标题。

边界处理:

与最邻近插值一样



五、用双三次插值算法实现图像的放大和缩小

实验原理:

双三次插值法与最邻近插值法和双线性插值除了在处理像素置加权不同外,其他的大致相同。双三次插值法在通过缩放比例公式找到原图像中对应点坐标时,会用周围16个像素点值加权得到,取该点与其他点的关系如下图所示:
在这里插入图片描述

因此,双三次插值法得到的图像会比其他两种方法得到的图像含有更多的细节,更加平滑,但计算量会很大。这里本次实验采用基于BiCubic基函数双三次插值法来进行计算。
BiCubic基函数:
在这里插入图片描述

其中取a=-0.5,图像为:

在这里插入图片描述

边界处理:

这里也与双线性插值法有所不同,双三次插值法是边界向外扩展两个像素,因为在计算像素值加权时,用到了周围16个点的像素,距其范围最远的有两行两列,因此,为了当取到边界坐标而不发生越界行为,应将图像向外扩展两个像素点。在此基础上的同时,也要做好最大值、最小值范围的限定,使其在有效数据内。



六、用最邻近插值算法、双线性插值法、双三次插值算法实现图像的旋转

实验原理:

因为这三种插值算法前面都有介绍它们放大、缩小的原理,所以在这里就不重复介绍了,与之区别的是,在之前用到的坐标对应公式是
在这里插入图片描述

但现在由于角度也在发生变化,需要据此找到新的转换公式。假设旋转有如下情况:
在这里插入图片描述

A(x,y)通过逆时针旋转 度后得到A‘(x’,y’),那么根据数学公式就有如下结果:
在这里插入图片描述

得到旋转矩阵R为 ,但由于一般是根据目标图像中的像素点找到原图像的像素点,因此在运算的时候,旋转矩阵R要取它的转置矩阵。
另外,对于旋转中心应该取在目标图像的中心位置而不是坐标为(0,0)的点,因此在旋转前后需要对像素点的坐标进行平移。
综上,有了旋转矩阵及旋转方法,那么就可以用最邻近插值法、双线性插值法、双三次插值法得到旋转后的图像了。

边界处理:

与之前的放大、缩小操作不同,这里由于图像旋转时其像素所占范围是一个以对角线为直径,对角线中点为圆点的圆,所以边界往往会比较大,为了保险起见,本次实验目标图像尺寸取的是对角线长度+6,并保证其为偶数。同时为了美观,将多余的像素颜色显示为图像窗口的背景颜色,其RGB为(240,240,240),只需要初始化目标矩阵时初始化一下就好了。

在编程中,读取一幅RGB图像并将其转换为灰度图像二值图像,通常使用图像处理库来实现。以Python语言为例,可以使用OpenCV库来完成这一过程。下面是一个简单的示例代码,展示了如何读取RGB图像,将其转换为灰度图像二值图像,并在一个窗口中分三个子窗口显示: ```python import cv2 import numpy as np # 读取RGB图像 rgb_image = cv2.imread('path_to_image.jpg') # 将RGB图像转换为灰度图像 gray_image = cv2.cvtColor(rgb_image, cv2.COLOR_BGR2GRAY) # 将灰度图像转换为二值图像 # 可以使用阈值方法,这里以简单阈值为例,阈值设置为128 _, binary_image = cv2.threshold(gray_image, 128, 255, cv2.THRESH_BINARY) # 创建一个窗口,并分成三列来显示三个图像 window_name = 'RGB, Gray and Binary Images' cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) cv2.resizeWindow(window_name, 900, 300) # 根据需要调整窗口大小 # 显示原RGB图像 cv2.imshow(window_name, np.hstack((rgb_image[:, :, ::-1], np.zeros_like(rgb_image)[:, :, :2]))) # 显示灰度图像 cv2.imshow(window_name, np.hstack((gray_image, np.zeros_like(gray_image, dtype=np.uint8)))) # 显示二值图像 cv2.imshow(window_name, np.hstack((binary_image, np.zeros_like(binary_image, dtype=np.uint8)))) # 等待按键,然后关闭所有窗口 cv2.waitKey(0) cv2.destroyAllWindows() ``` 在上述代码中,`cv2.imread`函数用于读取图像,`cv2.cvtColor`函数用于颜色空间转换,`cv2.threshold`函数用于将灰度图像转换为二值图像。使用`cv2.imshow`在同一个窗口中创建三个子窗口来显示图像。注意,在显示RGB图像时,需要将颜色通道顺序调整为OpenCV使用的BGR顺序,然后在最后加上两个透明通道来保持子窗口宽度一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值