在图像处理中,平移变换、旋转变换以及放缩变换是一些基础且常用的操作。这些几何变换并不改变图象的象素值,只是在图象平面上进行象素的重新排列。在一幅输入图象中,灰度值仅在整数位置上有定义。然而,输出图象[x,y]的灰度值一般由处在非整数坐标上的值来决定。这就需要插值算法来进行处理,常见的插值算法有最近邻插值、双线性插值和三次样条插值。
1、最近邻插值算法原理
最近邻插值,是指将目标图像中的点,对应到源图像中后,找到最相邻的整数点,作为插值后的输出。
如上图所示,目标图像中的某点投影到原图像中的位置为点P,此时易知,.
一个例子:
如下图所示,将一幅3X3的图像放大到4X4,用表示目标图像,表示原图像,我们有如下公式:
缺点: 用该方法作放大处理时,在图象中可能出现明显的块状效应
2、双线性插值
在讲双线性插值之前先看以一下线性插值,线性插值多项式为:
双线性插值就是线性插值在二维时的推广,在两个方向上做三次线性插值,具体操作如下图所示:
令为两个变量的函数,其在单位正方形顶点的值已知。假设我们希望通过插值得到正方形内任意点的函数值。则可由双线性方程:
来定义的一个双曲抛物面与四个已知点拟合。
首先对上端的两个顶点进行线性插值得:
类似地,再对底端的两个顶点进行线性插值有:
最后,做垂直方向的线性插值,以确定:
整理得:
3、基于opencv的实现
cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
参数:
| 参数 | 描述 |
|---|---|
| src | 【必需】原图像 |
| dsize | 【必需】输出图像所需大小 |
| fx | 【可选】沿水平轴的比例因子 |
| fy | 【可选】沿垂直轴的比例因子 |
| interpolation | 【可选】插值方式 |
插值方式:
| cv.INTER_NEAREST | 最近邻插值 |
| cv.INTER_LINEAR | 双线性插值 |
| cv.INTER_CUBIC | 基于4x4像素邻域的3次插值法 |
| cv.INTER_AREA | 基于局部像素的重采样 |
通常,缩小使用cv.INTER_AREA,放缩使用cv.INTER_CUBIC(较慢)和cv.INTER_LINEAR(较快效果也不错)。默认情况下,所有的放缩都使用cv.INTER_LINEAR。
使用python实现了最近邻插值算法
import cv2
import numpy as np
def nearest_resize(img, src_size):
h, w, c = img.shape
src = np.zeros((src_size[0], src_size[1], 3), dtype=np.uint8)
if h == src_size[0] and w == src_size[1]:
return img
for i in range(src_size[0]):
for j in range(src_size[1]):
# round()四舍五入的函数
src_x = round(i * (h / src_size[0]))
src_y = round(j * (w / src_size[1]))
src[i, j] = img[src_x, src_y]
return src
if __name__ == '__main__':
img = cv2.imread('F:/DataWhale/cv/imgs/4.jpeg')
cv2.imshow("img", img)
src = nearest_resize(img, (270, 480))
cv2.imshow("resize_img", src)
cv2.waitKey()
用自带的resize()实践
import cv2
if __name__ == "__main__":
img = cv2.imread('D:/image/yuner.jpg', cv2.IMREAD_UNCHANGED)
print('Original Dimensions : ',img.shape)
scale_percent = 30 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized = cv2.resize(img, dim, interpolation = cv2.INTER_LINEAR)
fx = 1.5
fy = 1.5
resized1 = cv2.resize(resized, dsize=None, fx=fx, fy=fy, interpolation = cv2.INTER_NEAREST)
resized2 = cv2.resize(resized, dsize=None, fx=fx, fy=fy, interpolation = cv2.INTER_LINEAR)
print('Resized Dimensions : ',resized.shape)
cv2.imshow("Resized image", resized)
cv2.imshow("INTER_NEAREST image", resized1)
cv2.imshow("INTER_LINEAR image", resized2)
cv2.waitKey(0)
cv2.destroyAllWindows()