专业网站建设顾问,0基础怎么学服装设计,深圳最便宜的物流公司,山东网站优化上采样与下采样
概念#xff1a;
上采样#xff1a; 放大图像#xff08;或称为上采样#xff08;upsampling#xff09;或图像插值#xff08;interpolating#xff09;#xff09;的主要目的 是放大原图像,从而可以显示在更高分辨率的显示设备上。 下采样#xff…上采样与下采样
概念
上采样 放大图像或称为上采样upsampling或图像插值interpolating的主要目的 是放大原图像,从而可以显示在更高分辨率的显示设备上。 下采样 缩小图像或称为下采样subsampled或降采样downsampled的主要目的 有两个 1、使得图像符合显示区域的大小2、生成对应图像的缩略图。 实现方法 上采样原理内插值 下采样原理(M/s) * (N/s)同比例缩小
插值方法
一:最邻近插值The nearest interpolation
设iu, jv(i, j为正整数 u, v为大于零小于1的小数下同)为待求象素坐标则待求象素灰 度的值 f(iu, jv) 如下图所示
若我们在A区域插入像素该像素值与ij的值相同同理若是在B区域插入像素这该像素值与i1,j的值相同。
缺点 如果在A区域插入过多的像素可能造成图像锯齿状。导致在某一区域的像素值相同导致失真
代码实现
import cv2
import numpy as np
def function(img):height,width,channels img.shapeemptyImagenp.zeros((800,800,channels),np.uint8) #建立一个空图像sh800/heightsw800/widthfor i in range(800):for j in range(800):xint(i/sh)yint(j/sw)emptyImage[i,j]img[x,y]return emptyImageimgcv2.imread(lenna.png)
print(img.shape)
zoomfunction(img)
print(zoom.shape)
cv2.imshow(nearest interp,zoom)
cv2.imshow(image,img)
cv2.waitKey(0)输出结果 原图像为512×512输出图像为800×800
二:双线性插值
公式 f(iu, jv) (1-u) * (1-v) * f(i, j) (1-u) * v * f(i, j1) u * (1-v) * f(i1, j) u * v * f(i1, j1)
看着有点懵 我们可以先看看单线性插值
公式: 其实就是一个比例关系我们想要输入的值是y像素值已知的位置点是x位置。y和y0的距离差与x和x0的距离差的比值应等于y1和y0的距离差与x1与x0的距离差的比值。从而推导出在单线性的情况下y的推导公式 了解了单线性插值我们推导双线性插值 先从x方向做两次单线性插值得R1和R2然后再在y方向做单线性插值 因为在图像计算中x1和x2,y1和y2都是相邻的点导致x2-x11,y2-y11 最后得到的结果其实就是 f(iu, jv) (1-u) * (1-v) * f(i, j) (1-u) * v * f(i, j1) u * (1-v) * f(i1, j) u * v * f(i1, j1) 注意插值算法并不是只能用在放大在插入像素点的同时忽略原图周围点即为缩小。
双线性插值有个额外的步骤中心对齐能够对双向插值的图像精度的提升 注意在默认的双线性插值时始终以左上角像素点进行对齐这就导致最右边的点始终没有参与插值。可能造成精度损失。
应用中心对齐后的双线性插值的代码实现
import numpy as np
import cv2
实现双线性插值def bilinear_interpolation(img,out_dim):src_h, src_w, channel img.shapedst_h, dst_w out_dim[1], out_dim[0]print (src_h, src_w , src_h, src_w)print (dst_h, dst_w , dst_h, dst_w)if src_h dst_h and src_w dst_w:return img.copy()#如果输入大小与原图大小相同则返回原图dst_img np.zeros((dst_h,dst_w,3),dtypenp.uint8)#建立一个预输出的全0图像scale_x, scale_y float(src_w) / dst_w, float(src_h) / dst_hfor i in range(3):for dst_y in range(dst_h):for dst_x in range(dst_w):#使用几何中心对称#如果使用直接方式src_xdst_x*scale_x#scale是比例通过同比例缩小/放大实现中心对齐src_x (dst_x 0.5) * scale_x - 0.5src_y (dst_y 0.5) * scale_y - 0.5#找到将用于计算插值的点的坐标src_x0 int(np.floor(src_x))src_x1 min(src_x0 1 ,src_w - 1)src_y0 int(np.floor(src_y))src_y1 min(src_y0 1, src_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]dst_img[dst_y,dst_x,i] int((src_y1 - src_y) * temp0 (src_y - src_y0) * temp1)return dst_imgif __name__ __main__:img cv2.imread(lenna.png)cv2.imshow(original picture,img)dst bilinear_interpolation(img,(700,700)) #放大#dst bilinear_interpolation(img,(200,200)) #缩小cv2.imshow(bilinear interp,dst)cv2.waitKey()
输出结果 中心对齐代码解读
src_x (dst_x 0.5) * scale_x - 0.5
src_y (dst_y 0.5) * scale_y - 0.5以这个图为例可以明显看出中心点在i0.5,j0.5也就是说先将原图的中心点找到然后按照放大/缩小的倍数最后还需要减去0.5的偏差值。 这里我参考了其他的博客 将公式变形srcXdstX* (srcWidth/dstWidth)0.5*(srcWidth/dstWidth-1) 相当于我们在原始的浮点坐标上加上了0.5*(srcWidth/dstWidth-1)这样一个控制因子这项的符号可正可负与srcWidth/dstWidth的比值也就是当前插值是扩大还是缩小图像有关有什么作用呢看一个例子假设源图像是33中心点坐标11目标图像是99中心点坐标44我们在进行插值映射的时候尽可能希望均匀的用到源图像的像素信息最直观的就是4,4映射到1,1现在直接计算srcX4*3/91.33331也就是我们在插值的时候所利用的像素集中在图像的右下方而不是均匀分布整个图像。现在考虑中心点对齐srcX(40.5)*3/9-0.51刚好满足我们的要求.