图像金字塔(Image Pyramid)
图像金字塔最初用于机器视觉和图像压缩,一幅图像的金字塔是一系列以金字塔形状排列的分辨率逐步降低,且来源于同一张原始图的图像集合。其通过梯次向下采样获得,直到达到某个终止条件才停止采样。
金字塔的底部是待处理图像的高分辨率表示,而顶部是低分辨率的近似。我们将一层一层的图像比喻成金字塔,层级越高,则图像越小,分辨率越低。
- 高斯金字塔 ( Gaussian pyramid): 用来向下/降采样,主要的图像金字塔
- 拉普拉斯金字塔(Laplacian pyramid): 用来从金字塔低层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原,配合高斯金字塔一起使用。
两者的区别:高斯金字塔用来向下降采样图像,注意降采样其实是由金字塔底部向上采样,分辨率降低,它和我们理解的金字塔概念相反;而拉普拉斯金字塔则用来从金字塔底层图像中向上采样重建一个图像。
- 对图像向上采样:pyrUp函数
- 对图像向下采样:pyrDown函数
注意:
- 向下与向上采样,是对图像的尺寸而言的(和金字塔的方向相反),向上就是图像尺寸加倍,向下就是图像尺寸减半。而如果我们按上图中演示的金字塔方向来理解,金字塔向上图像其实在缩小,这样刚好是反过来了。
- PryUp和PryDown不是互逆的,即PryUp不是降采样的逆操作。这种情况下,图像首先在每个维度上扩大为原来的两倍,新增的行(偶数行)以0填充。然后给指定的滤波器进行卷积(实际上是一个在每个维度都扩大为原来两倍的过滤器)去估计“丢失”像素的近似值。PryDown( )是一个会丢失信息的函数。
参考链接:
高斯金字塔
高斯金字塔是通过高斯平滑和亚采样获得一系列下采样图像,也就是说第K层高斯金字塔通过平滑、亚采样就可以获得K+1层高斯图像,高斯金字塔包含了一系列低通滤波器,其截至频率从上一层到下一层是以因子2逐渐增加,所以高斯金字塔可以跨越很大的频率范围。
-
对图像的向下取样操作,即缩小图像。
为了获取层级为 G_i+1 的金字塔图像,方法步骤如下:- 对图像G_i进行高斯内核卷积,进行高斯模糊;
- 将所有偶数行和列去除。
得到的图像即为G_i+1的图像,显而易见,结果图像只有原图的四分之一。通过对输入图像G_i(原始图像)不停迭代以上步骤就会得到整个金字塔。同时我们也可以看到,向下取样会逐渐丢失图像的信息。以上就是对图像的向下取样操作,即缩小图像。
-
对图像的向上取样,即放大图像
方法步骤如下:- 将图像在每个方向扩大为原来的两倍,新增的行和列以0填充
- 使用先前同样的内核(乘以4)与放大后的图像卷积,获得 “新增像素”的近似值
得到的图像即为放大后的图像,但是与原来的图像相比会发觉比较模糊,因为在缩放的过程中已经丢失了一些信息,如果想在缩小和放大整个过程中减少信息的丢失,这些数据形成了拉普拉斯金字塔。
拉普拉斯金字塔
拉普拉斯金字塔第i层的数学定义:
L
i
=
G
i
−
U
P
(
G
i
+
1
)
⊗
G
5
×
5
式
中
的
G
i
表
示
第
i
层
的
图
像
。
而
U
P
(
)
操
作
是
将
源
图
像
中
位
置
为
(
x
,
y
)
的
像
素
映
射
到
目
标
图
像
的
(
2
x
+
1
,
2
y
+
1
)
位
置
,
即
在
进
行
向
上
取
样
。
符
号
⊗
表
示
卷
积
,
G
5
×
5
为
5
×
5
的
高
斯
内
核
。
L_i=G_i-UP(G_{i+1})\otimes\mathcal{G}_{5×5} \\ 式中的G_i表示第i层的图像。而UP()操作是将源图像中位置为\\(x,y)的像素映射到目标图像的(2x+1,2y+1)位置,即在进行\\向上取样。符号\otimes表示卷积,\mathcal{G}_{5×5} 为{5×5} 的高斯内核。
Li=Gi−UP(Gi+1)⊗G5×5式中的Gi表示第i层的图像。而UP()操作是将源图像中位置为(x,y)的像素映射到目标图像的(2x+1,2y+1)位置,即在进行向上取样。符号⊗表示卷积,G5×5为5×5的高斯内核。
pryUp,就是在进行上面这个式子的运算。因此,可以直接用OpenCV进行拉普拉斯运算:
L
i
=
G
i
−
P
y
r
U
P
(
G
i
+
1
)
L_i=G_i-PyrUP(G_{i+1})
Li=Gi−PyrUP(Gi+1)
将降采样之后的图像再进行上采样操作,然后与之前还没降采样的原图进行做差得到残差图!为还原图像做信息的准备。
也就是说,拉普拉斯金字塔是通过源图像减去先缩小后再放大的图像的一系列图像构成的。保留的是残差!
注意: 上采样和下采样是非线性处理,不可逆,有损的处理。
cv2.pyrDown
先对图像进行高斯平滑,然后再进行降采样
pyrDown(src[, dst[, dstsize[, borderType]]]) -> dst
- src:输入的图像
- dstsize:降采样之后的目标图像的大小,它是有默认值的,如果我们调用函数的时候不指定第三个参数,那么这个值是按照
S i z e ( ( s r c . c o l s + 1 ) / 2 , ( s r c . r o w s + 1 ) / 2 ) Size((src.cols+1)/2, (src.rows+1)/2) Size((src.cols+1)/2,(src.rows+1)/2)
计算的。不管你自己如何指定这个参数,一定必须保证满足以下关系式:
{ ∣ d s t s i z e . w i d t h ∗ 2 − s r c . c o l s ∣ ≤ 2 ∣ d s t s i z e . h e i g h t ∗ 2 − s r c . r o w s ∣ ≤ 2 \begin{cases} |dstsize.width * 2 - src.cols| ≤ 2\\ |dstsize.height * 2 - src.rows| ≤ 2 \end{cases} {∣dstsize.width∗2−src.cols∣≤2∣dstsize.height∗2−src.rows∣≤2
cv2.pyrUp
先对图像进行升采样(将图像尺寸行和列方向增大一倍),然后再进行高斯平滑
pyrUp(src[, dst[, dstsize[, borderType]]]) -> dst
- src:输入的图像
- dstsize:升采样之后的目标图像的大小,在默认的情况下,这个尺寸大小是按照
S i z e ( s r c . c o l s ∗ 2 , s r c . r o w s ∗ 2 ) Size(src.cols*2, src.rows*2) Size(src.cols∗2,src.rows∗2)
来计算的。如果要指定大小,那么一定要满足下面的条件:
{ / / 如 果 w i d t h 是 偶 数 , 那 么 必 须 d s t s i z e . w i d t h 是 s r c . c o l s 的 2 倍 ∣ d s t s i z e . w i d t h − s r c . c o l s ∗ 2 ∣ ≤ ( d s t s i z e . w i d t h m o d 2 ) ; ∣ d s t s i z e . h e i g h t − s r c . r o w s ∗ 2 ∣ ≤ ( d s t s i z e . h e i g h t m o d 2 ) ; \begin{cases} //如果width是偶数,那么必须dstsize.width是src.cols的2倍\\ |dstsize.width - src.cols * 2| ≤ (dstsize.width mod 2); \\ |dstsize.height - src.rows * 2| ≤ (dstsize.height mod 2); \end{cases} ⎩⎪⎨⎪⎧//如果width是偶数,那么必须dstsize.width是src.cols的2倍∣dstsize.width−src.cols∗2∣≤(dstsize.widthmod2);∣dstsize.height−src.rows∗2∣≤(dstsize.heightmod2);
示例
def pyramid_image(image):
"""高斯图像金字塔"""
level = 4
temp = image.copy() # 备份image
pyramid_images = []
for i in range(level):
dst = cv.pyrDown(temp) # PyrDown降采样
pyramid_images.append(dst)
cv.imshow("pyramid_down_" + str(i + 1), dst)
temp = dst.copy()
return pyramid_images
def laplace_image(image):
"""拉普拉斯图像金字塔"""
pyramid_images = pyramid_image(image)
level = len(pyramid_images)
for i in range(level - 1, -1, -1):
if i - 1 < 0:
expand = cv.pyrUp(pyramid_images[i], dstsize=image.shape[:2])
lpls = cv.subtract(image, expand)
cv.imshow("laplace_" + str(i), lpls)
else:
expand = cv.pyrUp(pyramid_images[i], dstsize=pyramid_images[i - 1].shape[:2])
lpls = cv.subtract(pyramid_images[i - 1], expand)
cv.imshow("laplace_" + str(i), lpls)
注意:
注意图像大小需要是n*n的
结果:
- 高斯图像金字塔
- 拉普拉斯图像金字塔(不是纯黑的图,有白色的线的,是保留了降采样过程中残差的图)
参考链接: