效果
理论部分
在进行图片尺寸调整时,目标图像像素是根据所对应的原图像像素值进行取值,而这个取值计算过程是根据对应的原图像像素值的邻近的四个整数像素值进行双线性运算得到。
- 在x方向做插值,即求出直线R1R2
- 在直线R1R2上求出坐标y(在y方向做插值)
- 整合式子即为
- 可以理解为,先根据x轴方向的比例关系求出R1,R2的像素对象,再由R1,R2像素对象做y轴上的比例运算求出直线R1R2上确定的像素对象点。
- 也可以先做y方向插值,再做x方向插值
优化:
常规方法,目标图片所对应原图片对应的情况下:
这时会出现一个问题:
当我们把5x5图像调整为3x3的时候,如果以左上角为原点进行计算,则图像会出现失真和丢失像素值的问题(右侧和下侧的像素失真严重)
最好的方法就是,两个图像的几何中心重合,并且目标图像的每个像素之间都是等间隔的,并且都和两边有一定的边距
我们设原图像和目标图像都要平移z距离,才能使几何中心重合
-
step1:先列出原图像和目标图像几何中心 如原图片几何中心坐标X=(M-1)/2 , y = (M-1)/2
-
step2:使几何中心相同:
-
step3:计算得到结果z=1/2,式子为:(Src表示原图片,dst表示目标图片)
-
双线性差值法的计算比最邻近插值法复杂,计算量较大,但没有灰度不连续的缺点,图像看起来更光滑
代码部分
"""
@author: Hanley-Yang
彩色图像的双线性插值
"""
import numpy as np
import cv2
def bilinear_interpolation(img, outDim):
srcH, srcW, channel = img.shape
dstH, dstW = outDim[0], outDim[1]
#如果原图像和输出图像尺寸一致,则直接返回原图像
if srcH == dstH and srcW == dstW:
return img.copy()
dstImg = np.zeros((dstH,dstW,3),dtype=np.uint8)
scaleX,scaleY = float(srcW) / dstW, float(srcH) / dstH
for i in range(channel):
for dstY in range(dstH):
for dstX in range(dstW):
#找到输出图片的像素对应的原图像的像素坐标x和y
#使原图像和输出图像的几何中心对应
#srcX + 0.5 = (dstX + 0.5) * scale
srcX = (dstX + 0.5) * scaleX - 0.5
srcY = (dstY + 0.5) * scaleY - 0.5
#根据原图像对应的像素坐标进行插值计算
#X0,X1,Y0,Y1,坐标两两组合对应着最邻近的四个像素值
srcX0 = int(np.floor(srcX)) #np.floor向下取整
srcX1 = min(srcX0 + 1,srcW - 1) #srcW-1保证不越界
srcY0 = int(np.floor(srcY))
srcY1 = min(srcY0 + 1,srcH - 1)
#计算插值,求对应原图像像素所在的x的直线,再算出直线x上的(x,y)像素对象
temp0 = (srcX1 - srcX) * img[srcY0,srcX0,i] + (srcX-srcX0)*img[srcY0,srcX1,i]
temp1 = (srcX1 - srcX) * img[srcY1,srcX0,i] + (srcX-srcX0)*img[srcY1,srcX1,i]
dstImg[dstY,dstX,i] = int((srcY1-srcY) * temp0 + (srcY - srcY0) * temp1)
return dstImg
if __name__ == '__main__':
img = cv2.imread('Euphonium.png')
dst = bilinear_interpolation(img,(1080,1920))
# 保存处理后的图片到当前目录
cv2.imwrite("bilinear interpolation.png",dst)
cv2.imshow('bilinear interpolation',dst)
cv2.waitKey()