Opencv入门系列九
主要内容:图像金字塔是同一图像不同分辨率的子图集合,是通过对原图像不断地向下采样而产生的,即由高分辨率的图像产生低分辨率的近似图像。
- 高斯金字塔
- 拉普拉斯金字塔
图像金字塔是每上一层都是经过下层的一次高斯滤波和一次采样生成。
可得如下图的图像金字塔:
通常情况下,每向上移动一级,图像的宽和高都降低为原来的二分之一。
1.高斯金字塔
下面是一种简单的向上采样形式,如下图:
采样采用了高斯核,使原来的像素点周围补零,补的像素点为原来的三倍。
在向下采样中,我们需要丢失部分像素点,比如丢弃偶数列和行,等等操作。所以如果原图像在进行一次向下采样再进行一次向上采样后得到的图像将不再是原图像的样子。
向上采样:由低像素到高像素,补零行和列
向下采样:由高像素到低像素,删除原行和列
1.1向下采样
在OpenCV中有提供了函数cv2.pyrDown()实现向下采样(包含一次高斯滤波),其语法格式如下:
● dst:目标图像。
● src:原图像。
● dstsize:目标图像的大小。默认情况下,输出图像的大小为Size((src.cols + 1)/2 ,(src.rows + 1)/2)。
而且在任何情况下,图像尺寸必须满足如下条件:
|dst. width∗2-src. cols|≤2
|dst. height∗2-src. rows|≤2
● borderType:边界填充方式,默认值为BORDER_DEFAULT,且这里仅支持BORDER_DEFAULT。
下面简单的使用一下这个函数:
import cv2
import numpy as np
img = cv2.imread("Resources/12.jpg",cv2.IMREAD_GRAYSCALE)
pyrDownImg = cv2.pyrDown(img)
cv2.imshow("12",img)
cv2.imshow("pyrDown",pyrDownImg)
cv2.waitKey(0)
1.2向上采样
在OpenCV中有提供了函数cv2.pyrUp()实现向上采样(包含一次高斯滤波),其语法格式如下:
● dst:目标图像。
● src:原图像。
● dstsize:目标图像的大小。默认情况下,目标图像的大小为Size(src.cols×2, src.rows×2)。
而且在任何情况下,图像尺寸必须满足如下条件:
|dst. width-src. cols×2|≤mod(dst. widh,2)
|dst. height-src. rows×2|≤mod(dst. height,2)
● borderType:边界填充方式,默认值为BORDER_DEFAULT,且这里仅支持BORDER_DEFAULT。
下面简单使用一下这个函数:
import cv2
import numpy as np
img = cv2.imread("Resources/12.jpg",cv2.IMREAD_GRAYSCALE)
pyrUpImg = cv2.pyrUp(img)
pyrUpImg2 = cv2.pyrUp(pyrUpImg)
print(img)
print(pyrUpImg)
print(pyrUpImg2)
cv2.imshow("img",img)
cv2.imshow("pyrUpImg",pyrUpImg)
cv2.imshow("pyrUpImg2",pyrUpImg2)
cv2.waitKey(0)
2.探讨可逆性
如下是一个简单的实验程序:
import cv2
import numpy as np
img = cv2.imread("Resources/12.jpg",cv2.IMREAD_GRAYSCALE)
pyrUpImg = cv2.pyrUp(img)
pyrDownImg = cv2.pyrDown(img)
UpToDown = cv2.pyrDown(pyrUpImg)
DownToUp = cv2.pyrUp(pyrDownImg)
cv2.imshow("img",img)
cv2.imshow("UpToDown",UpToDown)
cv2.imshow("DownToUp",DownToUp)
cv2.waitKey(0)
从实验结果看出,两种方式都无法还原原图效果。且先向上再向下的采样会导致图像严重失真。
3.拉普拉斯金字塔
拉普拉斯金字塔:可以在有限次向下采样后,经过有限次向上采样获取原图像。如下:
L[i] = G[i] - pyrUp(G[i+1])
● L[i]:拉普拉斯金字塔中的第i层。
● G[i]:高斯金字塔中的第i层。
在每一次拉普拉斯向下采样的过程中,都保留了原来的部分,所以可以通过系列运算经过向上采样得到原图。
Li = 高斯i层 - 高斯向上(高斯i+1)层
复原过程
G[i] = L[i] + pyrUp(G[i+1])
import cv2
import numpy as np
G0 = cv2.imread("Resources/12.jpg",cv2.IMREAD_GRAYSCALE)
G1 = cv2.pyrDown(G0)
G2 = cv2.pyrDown(G1)
G3 = cv2.pyrDown(G2)
L0 = G0 - cv2.pyrUp(G1) # 为了方便理解采用这种方式
L1 = G1 - cv2.pyrUp(G2) # 为了方便理解采用这种方式
L2 = G2 - cv2.pyrUp(G3) # 为了方便理解采用这种方式
cv2.imshow("L0",L0)
cv2.imshow("L1",L1)
cv2.imshow("L2",L2)
cv2.waitKey(0)
通过拉普拉斯金字塔复原:
import cv2
import numpy as np
G0 = cv2.imread("Resources/12.jpg",cv2.IMREAD_GRAYSCALE)
G1 = cv2.pyrDown(G0)
G2 = cv2.pyrDown(G1)
G3 = cv2.pyrDown(G2)
# ================= 获取拉普拉斯金字塔
L0 = G0 - cv2.pyrUp(G1) # 为了方便理解采用这种方式
L1 = G1 - cv2.pyrUp(G2) # 为了方便理解采用这种方式
L2 = G2 - cv2.pyrUp(G3) # 为了方便理解采用这种方式
# ================= 复原
G0 = L0 + cv2.pyrUp(G1)
G1 = L1 + cv2.pyrUp(G2)
G2 = L2 + cv2.pyrUp(G3)
cv2.imshow("L0",L0)
cv2.imshow("L1",L1)
cv2.imshow("L2",L2)
cv2.waitKey(0)