OpenCV 图像金字塔

在某些情况下,我们需要在不同的分辨率下处理(相同的)图像;
例如,当在图像中搜索某个东西时,比如人脸,我们不确定该对象在该图像中的大小,在这种情况下,我们需要创建一组具有不同分辨率的相同图像,并在所有这些图像中搜索对象,这些具有不同分辨率的图像集被称为图像金字塔
在这里插入图片描述

高斯金字塔

高斯金字塔中的高阶(低分辨率)是通过去除低阶(高分辨率)图像中连续的行和列而形成的,我们可以使用cv.pyrDown()和cv.pyrUp()函数找到高斯金字塔

dst=cv.pyrDown(src[,st[,dstsize[,borderType]]])

dst:目标图像
scr:为原始图像
borderType:为边界类型,默认为BORDER_DEFAULT,默认情况下,输出图像的大小长宽为原图像的一半

img = cv.imread('./opencv_dataset/cv_1.jpg',0) # 灰色图像
r1 = cv.pyrDown(img)
r2 = cv.pyrDown(r1)
r3 = cv.pyrDown(r2)

print(img.shape)
print(r1.shape)
print(r2.shape)
print(r3.shape)
plt.subplot(1,4,1),plt.imshow(img,cmap = 'gray')
plt.title('img'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,2),plt.imshow(r1,cmap = 'gray')
plt.title('r1'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,3),plt.imshow(r2,cmap = 'gray')
plt.title('r2'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,4),plt.imshow(r3,cmap = 'gray')
plt.title('r3'), plt.xticks([]), plt.yticks([])

plt.show()
'''
(371, 355)
(186, 178)
(93, 89)
(47, 45)
'''

在这里插入图片描述

dst=cv.pyrUp(src[,st[,dstsize[,borderType]]])

dst:目标图像
scr:为原始图像
borderType:为边界类型,默认为BORDER_DEFAULT,默认情况下,输出图像的大小长宽为原图像的一半

img = cv.imread('./opencv_dataset/cv_1.jpg',0) # 灰色图像
r1 = cv.pyrUp(img)
r2 = cv.pyrUp(r1)
r3 = cv.pyrUp(r2)

print(img.shape)
print(r1.shape)
print(r2.shape)
print(r3.shape)
plt.subplot(1,4,1),plt.imshow(img,cmap = 'gray')
plt.title('img'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,2),plt.imshow(r1,cmap = 'gray')
plt.title('r1'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,3),plt.imshow(r2,cmap = 'gray')
plt.title('r2'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,4),plt.imshow(r3,cmap = 'gray')
plt.title('r3'), plt.xticks([]), plt.yticks([])

plt.show()
'''
(371, 355)
(742, 710)
(1484, 1420)
(2968, 2840)
'''

在这里插入图片描述

pyrDown原理
img_1 = np.random.randint(0,10,size=100,dtype=np.uint8) # 注意数据类型!!
img_1 = img_1.reshape(10,10)
img_1
'''
array([[1, 6, 9, 9, 5, 9, 2, 8, 2, 4],
       [4, 2, 5, 2, 2, 4, 6, 5, 6, 5],
       [9, 1, 8, 9, 4, 3, 8, 6, 1, 5],
       [0, 5, 5, 3, 5, 0, 7, 9, 7, 3],
       [2, 1, 3, 8, 5, 4, 8, 4, 2, 8],
       [3, 6, 9, 7, 9, 9, 9, 8, 4, 6],
       [8, 3, 8, 1, 6, 9, 9, 7, 1, 6],
       [7, 7, 4, 9, 3, 7, 7, 7, 3, 5],
       [4, 1, 7, 9, 3, 0, 4, 0, 5, 2],
       [3, 8, 0, 3, 6, 0, 4, 6, 7, 1]], dtype=uint8)
'''
r1 = cv.pyrDown(img_1)
r1
'''
array([[4, 5, 5, 5, 5],
       [4, 5, 4, 5, 5],
       [3, 5, 6, 6, 5],
       [5, 6, 6, 7, 5],
       [5, 5, 4, 4, 4]], dtype=uint8)
'''

手动生成高斯核

kernel = np.array([[1,4,6,4,1],
                   [4,16,24,16,4],
                   [6,24,36,24,6],
                   [4,16,24,16,4],
                   [1,4,6,4,1]])
kernel
'''
array([[ 1,  4,  6,  4,  1],
       [ 4, 16, 24, 16,  4],
       [ 6, 24, 36, 24,  6],
       [ 4, 16, 24, 16,  4],
       [ 1,  4,  6,  4,  1]])
'''
kernel = kernel/256
kernel
'''
array([[0.00390625, 0.015625  , 0.0234375 , 0.015625  , 0.00390625],
       [0.015625  , 0.0625    , 0.09375   , 0.0625    , 0.015625  ],
       [0.0234375 , 0.09375   , 0.140625  , 0.09375   , 0.0234375 ],
       [0.015625  , 0.0625    , 0.09375   , 0.0625    , 0.015625  ],
       [0.00390625, 0.015625  , 0.0234375 , 0.015625  , 0.00390625]])
'''

高斯核与原图像进行卷积

dst = cv.filter2D(img_1,-1,kernel)
dst
'''
array([[4, 4, 5, 5, 5, 5, 5, 5, 5, 4],
       [4, 4, 5, 5, 5, 5, 5, 5, 5, 4],
       [4, 4, 5, 5, 4, 5, 5, 6, 5, 4],
       [3, 4, 5, 5, 5, 5, 6, 6, 5, 5],
       [3, 4, 5, 6, 6, 6, 6, 6, 5, 5],
       [4, 5, 6, 6, 7, 7, 7, 6, 5, 5],
       [5, 5, 6, 6, 6, 7, 7, 6, 5, 4],
       [5, 5, 6, 6, 5, 6, 6, 5, 4, 4],
       [5, 5, 5, 5, 4, 4, 4, 4, 4, 4],
       [4, 4, 5, 5, 4, 3, 3, 4, 4, 4]], dtype=uint8)
'''

除去偶数行和偶数列

dst_2 = np.zeros((5,5),dtype=np.uint8)
for i in range(10):
    if i%2==0:
        for j in range(10):
            if j%2==0:
                dst_2[int(i/2),int(j/2)] = dst[i,j]
dst_2
'''
array([[4, 5, 5, 5, 5],
       [4, 5, 4, 5, 5],
       [3, 5, 6, 6, 5],
       [5, 6, 6, 7, 5],
       [5, 5, 4, 4, 4]], dtype=uint8)
'''

该结果与使用cv.pyrDown()的结果对比

dst_2 == r1
'''
array([[ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True],
       [ True,  True,  True,  True,  True]])
'''
pyrUp原理
dst_2
'''
array([[4, 5, 5, 5, 5],
       [4, 5, 4, 5, 5],
       [3, 5, 6, 6, 5],
       [5, 6, 6, 7, 5],
       [5, 5, 4, 4, 4]], dtype=uint8)
'''

我们先使用pyrUp()函数看一下结果

up_1 = cv.pyrUp(dst_2)
up_1
'''
array([[4, 5, 5, 5, 5, 5, 5, 5, 5, 5],
       [4, 5, 5, 5, 5, 5, 5, 5, 5, 5],
       [4, 4, 5, 5, 5, 5, 5, 5, 5, 5],
       [4, 4, 5, 5, 5, 5, 5, 5, 5, 5],
       [4, 4, 5, 5, 6, 6, 6, 6, 5, 5],
       [4, 5, 5, 6, 6, 6, 6, 6, 5, 5],
       [5, 5, 6, 6, 6, 6, 6, 6, 5, 5],
       [5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
       [5, 5, 5, 5, 4, 4, 4, 4, 4, 4],
       [5, 5, 5, 5, 4, 4, 4, 4, 4, 4]], dtype=uint8)
'''

向上采样时,每个像素的右侧、下方分别插入零列和零行

dst_3 = np.zeros((10,10),dtype=np.uint8)
for i in range(10):
    if i%2==0:
        for j in range(10):
            if j%2==0:
                dst_3[i,j] = dst_2[int(i/2),int(j/2)]
dst_3
'''
array([[4, 0, 5, 0, 5, 0, 5, 0, 5, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [4, 0, 5, 0, 4, 0, 5, 0, 5, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [3, 0, 5, 0, 6, 0, 6, 0, 5, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [5, 0, 6, 0, 6, 0, 7, 0, 5, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
       [5, 0, 5, 0, 4, 0, 4, 0, 4, 0],
       [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=uint8)
'''

用向下采样时所使用的高斯滤波器对图像进行滤波

由于面积扩大四倍,且增加的部分都是0元素,整体均值会降为原来的1/4

为了确保像素值区间在向上采样后与原始图像保持一致,需要将高斯滤波器的系数乘以4

kernel = np.array([[1,4,6,4,1],
                   [4,16,24,16,4],
                   [6,24,36,24,6],
                   [4,16,24,16,4],
                   [1,4,6,4,1]])
kernel = kernel/256*4
kernel
'''
array([[0.015625, 0.0625  , 0.09375 , 0.0625  , 0.015625],
       [0.0625  , 0.25    , 0.375   , 0.25    , 0.0625  ],
       [0.09375 , 0.375   , 0.5625  , 0.375   , 0.09375 ],
       [0.0625  , 0.25    , 0.375   , 0.25    , 0.0625  ],
       [0.015625, 0.0625  , 0.09375 , 0.0625  , 0.015625]])
'''

进行高斯滤波

dst_4 = cv.filter2D(dst_3,-1,kernel)
dst_4
'''
array([[4, 4, 5, 5, 5, 5, 5, 5, 5, 5],
       [4, 4, 5, 5, 5, 5, 5, 5, 5, 5],
       [4, 4, 5, 5, 5, 5, 5, 5, 5, 5],
       [4, 4, 5, 5, 5, 5, 5, 5, 5, 5],
       [4, 4, 5, 5, 6, 6, 6, 6, 5, 5],
       [4, 5, 5, 6, 6, 6, 6, 6, 5, 5],
       [5, 5, 6, 6, 6, 6, 6, 6, 5, 5],
       [5, 5, 5, 5, 5, 5, 5, 5, 5, 4],
       [5, 5, 5, 5, 4, 4, 4, 4, 4, 4],
       [5, 5, 5, 4, 4, 4, 4, 4, 4, 4]], dtype=uint8)
'''

该结果与使用cv.pyrUp()的结果对比

dst_4==up_1
'''
array([[ True, False,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True, False,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
        False],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True, False,  True,  True,  True,  True,  True,
         True]])
'''
#结果会有一些误差
采样可逆性

一幅图像先向下采样,再向上采样,虽然会恢复为原始大小,图像看起来相似,但是像素值是不一致的

import matplotlib.pyplot as plt
import cv2 as cv
img = cv.imread('E:/opencv/images/cameraman.tif',0) # 灰色图像

r1 = cv.pyrDown(img)
r2 = cv.pyrDown(r1)
r3 = cv.pyrDown(r2)

u1 = cv.pyrUp(r1)
u2 = cv.pyrUp(r2)
u3 = cv.pyrUp(r3)

plt.subplot(2,4,1),plt.imshow(img,cmap = 'gray')
plt.title('img'), plt.xticks([]), plt.yticks([])
plt.subplot(2,4,2),plt.imshow(r1,cmap = 'gray')
plt.title('r1'), plt.xticks([]), plt.yticks([])
plt.subplot(2,4,3),plt.imshow(r2,cmap = 'gray')
plt.title('r2'), plt.xticks([]), plt.yticks([])
plt.subplot(2,4,4),plt.imshow(r3,cmap = 'gray')
plt.title('r3'), plt.xticks([]), plt.yticks([])
plt.subplot(2,4,5),plt.imshow(img,cmap = 'gray')
plt.title('img'), plt.xticks([]), plt.yticks([])
plt.subplot(2,4,6),plt.imshow(u1,cmap = 'gray')
plt.title('u1'), plt.xticks([]), plt.yticks([])
plt.subplot(2,4,7),plt.imshow(u2,cmap = 'gray')
plt.title('u2'), plt.xticks([]), plt.yticks([])
plt.subplot(2,4,8),plt.imshow(u3,cmap = 'gray')
plt.title('u3'), plt.xticks([]), plt.yticks([])

plt.show()

在这里插入图片描述

图像看起来虽然相似,但是如我们将其相减,可以发现像素值是不一致的

L1 = cv.subtract(img,u1)
L2 = cv.subtract(r1,u2)
L3 = cv.subtract(r2,u3)

plt.subplot(1,3,1),plt.imshow(L1,cmap = 'gray')
plt.title('L1'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2),plt.imshow(L2,cmap = 'gray')
plt.title('L2'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3),plt.imshow(L3,cmap = 'gray')
plt.title('L3'), plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述

拉普拉斯金字塔

拉普拉斯金字塔是由高斯金字塔构成的,没有专门的函数
拉普拉斯金字塔图像只像边缘图像,它的大部分元素都是0,用于图像压缩
Laplacian金字塔中的层次是由高斯金字塔中的层次与高斯金字塔中其上层次的扩展后的层次之差形成的
在这里插入图片描述
使用cv.pyrDown()和cv.pyrUp()构造拉普拉斯金字塔

img = cv.imread('E:/persional/matlab/images/lena.bmp',0) # 灰色图像
r0 = img
r1 = cv.pyrDown(img)
r2 = cv.pyrDown(r1)
r3 = cv.pyrDown(r2)
L0 = r0 - cv.pyrUp(r1)
L1 = r1 - cv.pyrUp(r2)
L2 = r2 - cv.pyrUp(r3)

print(L0.shape)
print(L1.shape)
print(L2.shape)
'''
(512, 512)
(256, 256)
(128, 128)
'''
plt.subplot(1,4,1),plt.imshow(img,cmap = 'gray')
plt.title('img'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,2),plt.imshow(L0,cmap = 'gray')
plt.title('L0'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,3),plt.imshow(L1,cmap = 'gray')
plt.title('L1'), plt.xticks([]), plt.yticks([])
plt.subplot(1,4,4),plt.imshow(L2,cmap = 'gray')
plt.title('L2'), plt.xticks([]), plt.yticks([])

plt.show()

在这里插入图片描述
拉普拉斯金子塔的作用在于,能够恢复高分辨率的图像

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值