1. 图片缩小
比例缩放前后两点 P0(x0,y0)P_0(x_0, y_0)P0(x0,y0)、P(x,y)P(x,y)P(x,y) 之间的关系用矩阵形式可以表示为
[xy1]=[fx000fy0001][x0y01] \left[\begin{matrix} x \\ y \\ 1 \end{matrix}\right] =\left[\begin{matrix} f_x & 0 & 0\\ 0 & f_y & 0\\ 0 & 0 & 1 \end{matrix}\right] \left[\begin{matrix} x_0 \\ y_0 \\ 1 \end{matrix}\right] ⎣⎡xy1⎦⎤=⎣⎡fx000fy0001⎦⎤⎣⎡x0y01⎦⎤
在数字图像中,图像缩小是通过减少像素个数实现,关键在于怎么去掉一部分像素点,而尽可能保持原有图像的概貌特征。下面介绍两种简单的图像缩小技术。
为了理解算法,应该先把图像想成是连续的,然后再四舍五入取离散值。比如计算后得出,缩小后的图像点 (2,2)(2,2)(2,2) 的像素值与原图像 (2.1,2.8)(2.1, 2.8)(2.1,2.8) 处相等,就四舍五入取原图像 (2,3)(2,3)(2,3) 处的坐标。
为了便于叙述,放大或缩小前的图像为原图像 RRR,可理解为单词 rawrawraw,放大或缩小后的图像为新图像 SSS,RRR的后面一个字母。
-
最近邻采样
原图像为 R(x,y)R(x, y)R(x,y),新图像为 S(x,y)S(x, y)S(x,y),设原图像和新图像 xxx 方向和 yyy 方向比例分别为 rx,ryr_x, r_yrx,ry,这个 rx,ryr_x, r_yrx,ry 也可以看作是下采样的采样间隔。
为了方便理解缩小,把原图像看作是新图像的放大,则新图像在 (x,y)(x,y)(x,y) 处的灰度值 S(x,y)S(x,y)S(x,y),有
S(x,y)=R(rx⋅x,ry⋅y) S(x,y) = R(r_x\cdot x, r_y\cdot y) S(x,y)=R(rx⋅x,ry⋅y)
如果 rx⋅xr_x\cdot xrx⋅x 算出来是小数,四舍五入即可,其余同理。其实新图像的坐标 -
局部平均值采样
找出两次采样间的子块,然后求平均值为当前像素值。比如原图像大小为 4×44\times 44×4,要缩小为 2×22\times 22×2,则缩小后图像 (1,1)(1,1)(1,1) 的值就是原图像的左上角的 2×22\times 22×2 的局部单元像素的平均值。对于小数也差不多,四舍五入。在实际编程中,都是直接调用函数,不必为各种繁琐的四舍五入操心。
2. 图像放大
-
最近邻采样
和上面所述的差不多,举例说明。比如原来 10×1010\times 1010×10 的图片,放大到 15×1515\times 1515×15,即放大了 1.51.51.5 倍,要计算新图像在 (10,11)(10, 11)(10,11), 则对应原图像 (10/1.5,11/1.5)=(6.7,7.3)(10/1.5, 11/1.5)=(6.7, 7.3)(10/1.5,11/1.5)=(6.7,7.3) 处的像素值,四舍五入取整原图像 (7,7)(7, 7)(7,7) 处的像素值即可。 -
线性插值法
线性插值法就是找周围最近的几个点,线性组合取值。举个简单的例子说明。和刚刚的最近邻采样条件一样,也求 (10,11)(10,11)(10,11) 处的坐标。上面求处该坐标对应原图像 R(6.7,7.3)R(6.7, 7.3)R(6.7,7.3) 处的值,此时应找距离 R(6.7,7.3)R(6.7, 7.3)R(6.7,7.3) 最近的几个点,即 (6,7),(6,8),(7,7),(7,8)(6,7), (6,8), (7,7), (7,8)(6,7),(6,8),(7,7),(7,8) 四点加权来算新图像的像素值,距离近则权值大。大家可以自己在纸上画个图,可以先看 xxx 方向,再看 yyy 方向。
xxx 方向,根据距离远的权值小,有:
R(6.7,y)=(1−0.7)R(6,y)+0.7R(7,y) R(6.7,y) = (1-0.7)R(6,y) + 0.7R(7,y) R(6.7,y)=(1−0.7)R(6,y)+0.7R(7,y)
则可以算出 R(6.7,7)R(6.7, 7)R(6.7,7), R(6.7,8)R(6.7, 8)R(6.7,8)。再次使用加权可求 R(6.7,7.3)R(6.7, 7.3)R(6.7,7.3)
即有:
R(6.7,7.3)=(1−0.3)R(6.7,7)+0.3R(6.7,8) R(6.7, 7.3) = (1-0.3)R(6.7, 7) + 0.3R(6.7, 8) R(6.7,7.3)=(1−0.3)R(6.7,7)+0.3R(6.7,8)
最终算出原图像 R(6.7,7.3)R(6.7, 7.3)R(6.7,7.3) 处的像素值,也即新图像 (10,11)(10,11)(10,11) 处的像素值。
OpenCv实战
直接用 resize 函数即可实现放大缩小。
cv.resize(img, dsize, [interpolation])
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def show(img):
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB), cmap='gray', vmin=0, vmax=255)
plt.show()
img = cv.imread('pic/rabbit50x33.jpg') # 路径更换成新的图片
img_resize1 = cv.resize(img, (330, 500), interpolation=cv.INTER_NEAREST)
img_resize2 = cv.resize(img, (330, 500), interpolation=cv.INTER_LINEAR)
show(img)
show(np.hstack([img_resize1, img_resize2]))
本文介绍了图像缩放的两种基本技术——最近邻采样和局部平均值采样,详细阐述了这两种方法在图像缩小和放大过程中的应用。同时,通过线性插值法解释了更高级的放大技术。最后,通过OpenCV库的resize函数展示了如何在实践中实现图像的放大和缩小操作。
1880

被折叠的 条评论
为什么被折叠?



