图像金字塔与图像多分辨率的原理和opencv实现
- 1图像多分辨率及其实现
- 例子
- 2图像金字塔及其实现
- 2.1原理
- 2.2opencv中实现
- 2.3代码
1图像多分辨率及其实现
图像的多分辨率表示同一图像采用不同的采样方式,也可以通过一幅图像进行缩放得到不同分辨率的图像。比如姨夫500500的像素要缩小为250250,怎么办呢?
你可能想到的办法是直接在原图像上间隔采样,但这样会丢失很多原有图像的信息。再比如你想要将500500的图像放大一倍,变成10001000像素的,那你又怎么办呢?
图像处理中常用的处理图像缩放的方法就是插值。主要包括最近邻插值、双线性插值、双三次插值等,其中双三次插值是Photoshop等商业软件的标准内插方法。
双线性插值的公式如下:
我们用四个最近邻的位置(上下左右)去估计该点的像素值,充分利用了原图像的信息,并保证了图像的平滑。为了获得更好的平滑效果,你可以采用双三次内插,公式如下,它们的原理相同,只是采用的近邻数目不同。
讲了图像缩放的原理,下面说一下图像缩放在opencv中的实现,函数原型如下:
cv2.resize(src, dsize, dst, fx, fy, interpolation)
参数 | 描述 |
src | 【必需】原图像 |
dsize | 【必需】输出图像大小 |
fx | 【可选】沿水平方向的比例因子 |
fy | 【可选】沿竖直方向的比例因子 |
interpolation | 【可选】图像插值方式 |
上面讲述的三种插值方式的参数如下:
最近邻插值 | cv.INTER_NEAREST |
双线性插值 | cv.INTER_LINEAR |
双三次插值 | cv.INTER_CUBIC |
例子
import cv2
img1=cv2.imread('flower.png')
cv2.imshow('flower_show',img1)
scale_percent = 50 # percent of original size
width = int(img1.shape[1] * scale_percent / 100)
height = int(img1.shape[0] * scale_percent / 100)
dim = (width, height)
img2=cv2.resize(img1,dim,interpolation =cv2.INTER_AREA)
cv2.imshow('flower1_show',img2)
cv2.imwrite('flower1_show.jpg',img2)
cv2.waitKey()
cv2.destroyAllWindows()
原图像:
缩小一半图像(三次插值):
直觉上看,两幅图的效果没有差别。但如果你仔细观察的话,第二幅图的细节更加模糊了。
2图像金字塔及其实现
2.1原理
图像金字塔和第一节的图像多分辨率很相似,但存在一些差别。图像金字塔主要是想从不同的维度来对原图像进行表达,从而获得不同尺度下的细节。比如一幅512512的图像,可以降采样得到256256的图像,再降采样得到128*128的图像,继续这个过程可以得到不同级的图像。
图像金字塔的原理如下图所示:
为了保证降采样得到的图像更加逼近原图像,会对原来的图像进行平滑滤波器滤波,不同的滤波方法得到不同的图像金字塔,比如采用高斯低通滤波得到高斯金字塔。
为了将图像金字塔还原为原图像,一般会在降采样得到图像金字塔的过程中维护一个残差金字塔,也称拉普拉斯金字塔,具体的流程如上图所示。对降采样得到的图像进行上采样(伴随着插值滤波)得到和原图像分辨率相同的图像,然后和原图像作差得到残差图像。
2.2opencv中实现
opencv中提供了两个函数pyrUp和pyrDown用于实现高斯金字塔和拉普拉斯金字塔。
pyrUp函数完成了高斯低通滤波和降采样两个操作,可以方便地得到高斯金字塔。
pyrDown函数完成了上采样和插值滤波两个操作,可以结合高斯金字塔得到拉普拉斯金字塔。
2.3代码
import cv2 as cv
#高斯金字塔
def pyramid_image(image):
cv.imshow("timg1.jpg",image)
level = 2#金字塔的层数
temp = image.copy()#拷贝图像
pyramid_images = []
for i in range(level):
dst = cv.pyrDown(temp)
pyramid_images.append(dst)
cv.imshow("pyramid"+str(i), dst)
temp = dst.copy()
return pyramid_images
#拉普拉斯金字塔
def lpls_image(image):
pyramid_images = pyramid_image(image)
level = len(pyramid_images)
for i in range(level-1, -1, -1):#数组下标从0开始 i从金字塔层数-1开始减减
if (i-1)<0:#原图
expand = cv.pyrUp(pyramid_images[i])
lpls = cv.subtract(image, expand)
cv.imshow("lpls_%s" % i, lpls)
else:
expand = cv.pyrUp(pyramid_images[i])
lpls = cv.subtract(pyramid_images[i-1], expand)
cv.imshow("lpls_%s" % i, lpls)
img = cv.imread("timg.jpg")
lpls_image(img)
cv.waitKey(0)
cv.destroyAllWindows()
高斯金字塔:
拉普拉斯金字塔