上采样(放大图像)和下采样(缩小图像)(最邻近插值和双线性插值的理解和实现)

您所在的位置:网站首页 双线性插值的作用 上采样(放大图像)和下采样(缩小图像)(最邻近插值和双线性插值的理解和实现)

上采样(放大图像)和下采样(缩小图像)(最邻近插值和双线性插值的理解和实现)

2024-02-18 12:19| 来源: 网络整理| 查看: 265

上采样和下采样 什么是上采样和下采样?

• 缩小图像(或称为下采样(subsampled)或降采样(downsampled))的主要目的有 两个:1、使得图像符合显示区域的大小;2、生成对应图像的缩略图。 • 放大图像(或称为上采样(upsampling)或图像插值(interpolating))的主要目的 是放大原图像,从而可以显示在更高分辨率的显示设备上。 注意: 如果想放大一个图片或者一个图片,应该想到,当图片放大或缩小的时候,会增加或者减少像素点。比如说原来200×200的图片,要是想变成400×400的图片,就要多出3倍的像素点需要添加。而如何添加这些像素点就是问题的核心

原理:

上采样原理:内插值 (增加像素点) 下采样原理:(M/s) * (N/s) (等比例减少像素点)

最邻近插值The nearest interpolation 思想:

最邻近插值,思想就是他的名字,找插入像素点位置的最邻近的像素点,将其作为自己的像素值插入。 如图: 设i+u, j+v (i, j为正整数, u, v为大于零小于1的小数,下同)为待求象素坐标,则待求象素 灰度的值 f(i+u, j+v) 如下图所示: 在这里插入图片描述 如果在A区域插入像素点,该点的像素值就与(i,j)的像素值相同,同理,在B区域插入的像素点就与(i+1,j)的像素值相同。

算法实现: import cv2 import numpy as np """ 最邻近插值The nearest interpolation实现 """ def function(img,aim_height,aim_width): height,width,channels = img.shape #获得原图像的长宽和维度 empty_img = np.zeros((aim_height,aim_width,channels),np.uint8) #新建全0图像 transform_h = aim_height/height #找到长的放大/缩小倍数 transform_w = aim_width/width #找到宽的放大/缩小倍数 for i in range(aim_height): for j in range(aim_width): x = int(i/transform_h) #找到最近邻点(这个点必须取整) y = int(j/transform_w) empty_img[i,j]=img[x,y] #将最近邻点的数值赋予新图像 return empty_img img = cv2.imread("lenna.png") transform_picture = function(img,800,800) #800,800是新图像大小 cv2.imshow("transform picture",transform_picture) cv2.waitKey(0) 实现结果:

在这里插入图片描述

双线性插值: 单线性插值:

要想知道什么是双线性插值,我们先来研究单线性插值: 在这里插入图片描述 如图所示,我们想要求(x,y)的y坐标,现在已知:x,(x0,y0),(x1,y1),该怎么求? 通过等比例的方法:可以获得如下推论 在这里插入图片描述 最后的结果就是红框部分公式

双线性插值:

这时候我们再看双线性插值: 在这里插入图片描述 我们将其拆解为X方向和Y方向的单线性插值。 通过Q11和Q21能够获得R1的值,再通过Q12和Q22获得R2的值,最后通过R1和R2推得P的值。 具体推理过程如下: 在这里插入图片描述 由于图像双线性插值只会用相邻的4个点,因此上述公式的分母都是1。

几何中心对齐:

目前还存在有问题: 坐标系的选择问题:在这里插入图片描述 如果源图像和目标图像的原点(0,0)均选择左上角,然后根据插值公式计算目标图像每点像素,假设你需要将一幅5x5的图像缩小成3x3,那么源图像和目标图像各个像素之间的对应关系如下: 在这里插入图片描述 也就是说,图像当以左上角为对齐点来看,会使偏右偏下的原像素点的价值变低,新插值点受偏左偏上的原像素点影响更大。 那么,让坐标加1或者选择右下角为原点怎么样呢?很不幸,还是一样的效果,不过这次得到的图像将偏右偏下。 最好的方法就是,两个图像的几何中心重合,并且目标图像的每个像素之间都是等间隔的,并且都和两边有一定的边距。 公式如下: 在这里插入图片描述 这里老师进行了公式的推导: 在这里插入图片描述

算法实现: import cv2 import numpy as np """ 双线性插值实现 """ def bilinear_interpolation(img,out_dim): input_h,input_w,channels = img.shape out_h,out_w = out_dim[0],out_dim[1] if input_h == out_h and input_w == out_w: #若输出图像和输入图像要求相等,则输出原图像 return img.copy() empty_img = np.zeros((out_h,out_w,channels),np.uint8) scale_x, scale_y = float(out_h / input_h),float(out_w / input_w) for i in range(channels): for dst_y in range(out_h): for dst_x in range(out_w): #几何中心对齐 src_x = (dst_x + 0.5) / scale_x - 0.5 src_y = (dst_y + 0.5) / scale_y - 0.5 #找到插值周围点 src_x0 = int(np.floor(src_x)) src_x1 = min(src_x0 + 1, input_w - 1) src_y0 = int(np.floor(src_y)) src_y1 = min(src_y0 + 1, input_h - 1) #双线性插值公式计算 temp0 = (src_x1 - src_x) * img[src_y0, src_x0, i] + (src_x - src_x0) * img[src_y0, src_x1, i] temp1 = (src_x1 - src_x) * img[src_y1, src_x0, i] + (src_x - src_x0) * img[src_y1, src_x1, i] empty_img[dst_y, dst_x, i] = int((src_y1 - src_y) * temp0 + (src_y - src_y0) * temp1) return empty_img if __name__ == '__main__': img = cv2.imread('lenna.png') transform_picture = bilinear_interpolation(img,(800,800)) cv2.imshow('transform picture',transform_picture) cv2.waitKey() 实现结果:

在这里插入图片描述

最邻近插值与双线性插值的对比:

双线性差值法的计算比最邻近插值法复杂,计算量较大,但没有灰度不连续的缺点,图像看起来更光滑。 而最邻近插值更快,更简单。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3