简介
在图像处理中,平移变换、旋转变换以及放缩变换是一些基础且常用的操作。这些几何变换并不改变图象的象素值,只是在图象平面上进行象素的重新排列。在一幅输入图象 [ u , v ] [u,v] [u,v]中,灰度值仅在整数位置上有定义。然而,输出图象[x,y]的灰度值一般由处在非整数坐标上的 ( u , v ) (u,v) (u,v)值来决定。这就需要插值算法来进行处理,常见的插值算法有最近邻插值、双线性插值和三次样条插值。
算法理论介绍与推荐
最近邻插值算法原理
实现代码 numpy和cv2
import numpy as np
def near_insert_1color(pic_dt, resize, x_scale=None, y_scale=None):
"""
最近邻插值(图片 m * n * 图层)
param pic_dt: 为一个图片的一个图层的数据 len(pic_dt) == 2
param resize: set (长, 宽)
param x_scale: float 长度缩放大小
param y_scale: float 宽带缩放大小
"""
m, n = pic_dt.shape
# 获取新的图像的大小
if resize is None:
n_new, m_new = np.round(x_scale * n).astype(int), np.round(y_scale * m).astype(int)
else:
n_new, m_new = resize
fx, fy = n / n_new, m / m_new # src_{长}/dst_{长}, src_{宽}/dst_{宽}
# 初始化X, Y的位置点
idx_x_orign = np.array(list(range(n_new)) * m_new).reshape(m_new, n_new)
idx_y_orign = np.repeat(list(range(m_new)), n_new).reshape(m_new, n_new)
# 需要的近邻的位置
x_indx = np.round(idx_x_orign * fx).astype(int)
y_indx = np.round(idx_y_orign * fy).astype(int)
return pic_dt[y_indx, x_indx]
def near_insert(pic_dt_, resize, fx=None, fy=None):
# 三个通道分开处理再合并
if len(pic_dt_.shape) == 3:
out_img0 = near_insert_1color(pic_dt_[:,:,0], resize=resize, x_scale=fx, y_scale=fy)
out_img1 = near_insert_1color(pic_dt_[:,:,1], resize=resize, x_scale=fx, y_scale=fy)
out_img2 = near_insert_1color(pic_dt_[:,:,2], resize=resize, x_scale=fx, y_scale=fy)
out_img_all = np.c_[out_img0[:,:,np.newaxis], out_img1[:,:,np.newaxis], out_img2[:,:,np.newaxis]]
else:
out_img_all = near_insert_1color(pic_dt_, resize=resize, x_scale=fx, y_scale=fy)
return out_img_al
import cv2
"""
v2.resize(
src 【必需】原图像
dsize 【必需】输出图像所需大小 (长 , 宽) (shape[1], shape[0])
fx 【可选】沿水平轴的比例因子
fy 【可选】沿垂直轴的比例因子
interpolation 【可选】插值方式
)
cv.INTER_NEAREST 最近邻插值
cv.INTER_LINEAR 双线性插值
cv.INTER_CUBIC 基于4x4像素邻域的3次插值法
cv.INTER_AREA 基于局部像素的重采样
"""
# 读取图片
img = cv2.imread(pic_fil, cv2.IMREAD_UNCHANGED)
# cv2.resize 方法 放大1.5倍
resized1_5_img_near = cv2.resize(img
, dsize=None
, fx=1.5
, fy=1.5
, interpolation=cv2.INTER_NEAREST)
# 用自己写的函数实现近邻插值
out_img_all = near_insert(img, resize=None, fx=1.5, fy=1.5)
缺点: 用该方法作放大处理时,在图象中可能出现明显的块状效应
双线性插值算法
线性插值多项式:
双线性插值就是线性插值在二维时的推广,在两个方向上做三次线性插值,具体操作如下图所示:
映射方法
向前映射法
可以将几何运算想象成一次一个象素地转移到输出图像中。如果一个输入象素被映射到四个输出像素之间的位置,则其灰度值就按插值算法在4个输出象素之间进行分配。称为向前映射法,或象素移交影射。 注:从原图象坐标计算出目标图象坐标镜像、平移变换使用这种计算方法
向后映射法
向后映射法(或象素填充算法)是输出象素一次一个地映射回到输入象素中,以便确定其灰度级。如果一个输出象素被映射到4个输入象素之间,则其灰度值插值决定,向后空间变换是向前变换的逆。
注:从结果图象的坐标计算原图象的坐标
旋转、拉伸、放缩可以使用
解决了漏点的问题,出现了马赛克
实现
通常,缩小使用cv.INTER_AREA,放缩使用cv.INTER_CUBIC(较慢)和cv.INTER_LINEAR(较快效果也不错)。默认情况下,所有的放缩都使用cv.INTER_LINEAR。
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()