OpenCV的imgproc 模块:如何放大缩小图像?使用图像金字塔函数cv2.pyrUp、cv2.pyrDown一步搞定
一、目标
在这一章,
我们将学习图像金字塔
我们将学习这些函数:cv2.pyrUp(), cv2.pyrDown()
二、基本理论
通常,我们过去使用的是恒定大小的图像。 但是在某些情况下,我们需要使用不同分辨率的(相同)图像。 例如,当在图像中搜索某些东西(例如人脸)时,我们不确定对象在所述图像中将以多大的尺寸显示。 在这种情况下,我们将需要创建一组具有不同分辨率的相同图像,并在所有图像中搜索对象。 这些具有不同分辨率的图像集称为“图像金字塔”(因为当它们堆叠在底部时,最高分辨率的图像位于底部,最低分辨率的图像位于顶部时,看起来像金字塔)。
有两种图像金字塔:
1)高斯金字塔
2)拉普拉斯金字塔
高斯金字塔中的较高级别(低分辨率)是通过删除较低级别(较高分辨率)图像中的连续行和列而形成的。 然后,较高级别的每个像素由基础级别的5个像素的贡献与高斯权重形成。 通过这样做,M×N图像变成M / 2×N / 2图像。 因此面积减少到原始面积的四分之一。 它称为八度音阶。 当我们在金字塔中越靠上时(即分辨率下降),这种模式就会继续。 同样,在扩展时,每个级别的面积变为4倍。 我们可以使用cv2.pyrDown()
和cv2.pyrUp()
函数找到高斯金字塔。
三、图像金字塔(Image Pyramids)
3.1 高斯金字塔
cv2.pyrUp()函数
dst = cv2.pyrUp ( InputArray src,
const Size & dstsize = Size(),
int borderType = BORDER_DEFAULT
)
参数 | 说明 |
---|---|
src | 输入图像 |
dst | 输出图像。 它具有指定的大小,并且与src具有相同的类型 |
dstsize | 输出图像的大小 |
borderType | 像素外推方法,请参见BorderTypes(仅支持BORDER_DEFAULT) |
BorderTypes
BorderTypes参数 | 说明 |
---|---|
cv2.BORDER_CONSTANT | iiiiii-abcdefgh-iiiiiii with some specified i |
cv2.BORDER_REPLICATE | aaaaaa-abcdefgh-hhhhhhh |
cv2.BORDER_REFLECT | fedcba-abcdefgh-hgfedcb |
cv2.BORDER_WRAP | cdefgh-abcdefgh-abcdefg |
cv2.BORDER_REFLECT_101 | gfedcb-abcdefgh-gfedcba |
cv2.BORDER_TRANSPARENT | uvwxyz-abcdefgh-ijklmno |
cv2.BORDER_REFLECT101 | same as BORDER_REFLECT_101 |
cv2.BORDER_DEFAULT | same as BORDER_REFLECT_101 |
cv2.BORDER_ISOLATED | do not look outside of ROI |
上采样图像,然后使其模糊。
默认情况下,输出图像的大小计算为Size(src.cols \ * 2,(src.rows \ * 2),但是在任何情况下,都应满足以下条件:
该函数执行高斯金字塔构造的升采样步骤,尽管它实际上可以用于构造拉普拉斯金字塔。 首先,它甚至通过注入零行和零列来对源图像进行升采样,然后将结果与与pyrDown中相同的内核乘以4进行卷积。
cv2.pyrDown()函数
dst = cv2.pyrDown ( InputArray src,
const Size & dstsize = Size(),
int borderType = BORDER_DEFAULT
)
参数 | 说明 |
---|---|
src | 输入图像 |
dst | 输出图像。 它具有指定的大小,并且与src具有相同的类型 |
dstsize | 输出图像的大小 |
borderType | 像素外推方法,请参见BorderTypes(不支持BORDER_CONSTANT ) |
模糊图像并对其进行下采样。
默认情况下,输出图像的大小计算为Size((src.cols + 1)/ 2,(src.rows + 1)/ 2),但是在任何情况下,都应满足以下条件:
该函数执行高斯金字塔构造的下采样步骤。 首先,它将源映像与内核进行卷积:
然后,去除偶数行和列对图像进行下采样。
3.2 小结
注意:我们向下采样缩小图像的时候, 我们实际上丢失了一些信息。
举例演示1
原图展示:
#######图像金字塔########
import numpy as np
import cv2
import matplotlib.pyplot as plt
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('cat2.jpg')
cv_show(img,'img')
print(img.shape)
#下采样,缩小图像
down_img = cv2.pyrDown(img)
cv_show(down_img,'down_img')
print(down_img.shape)
cv2.imwrite('down_img.jpg',down_img)
#上采样,放大图像
up_img = cv2.pyrUp(img)
cv_show(up_img,'up_img')
print(up_img.shape)
cv2.imwrite('up_img.jpg',up_img)
运行结果:
-
原图大小:
原图的shape值(135, 240, 3) -
下采样结果:
下采样的shape值(68, 120, 3) -
上采样结果:
上采样的shape值(270, 480, 3)
举例演示2
将图像进行一次上采样、再进行一次下采样,得到的图像与原图像相比有什么不同呢?请看下面代码:
#######图像金字塔########
import numpy as np
import cv2
import matplotlib.pyplot as plt
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('lena.jpg')
cv_show(img,'img')
print(img.shape)
#上采样,放大图像
up_img = cv2.pyrUp(img)
print(up_img.shape)
#下采样,缩小图像
img2 = cv2.pyrDown(up_img)
print(img2.shape)
merge = np.hstack((img,img2))
cv_show(merge,'compare')
cv2.imwrite('merge.jpg',merge)
运行结果:
原图和变换后的图像尺寸大小都是(263, 263, 3);
但是通过对比可以看出,经过上采样和下采样变换后的图像比原图更模糊了,这是因为在进行下采样时降低了分辨率,因为一旦降低分辨率,便会丢失部分数据。
3.2 拉普拉斯金字塔
拉普拉斯金字塔由高斯金字塔形成。 没有专用功能。 拉普拉斯金字塔图像仅像边缘图像。 它的大多数元素为零。 它们用于图像压缩。 拉普拉斯金字塔的层由高斯金字塔的层与高斯金字塔的高层的扩展版本之间的差形成:
举例演示
#######图像金字塔########
import numpy as np
import cv2
import matplotlib.pyplot as plt
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
img = cv2.imread('cat.jpg')
#上采样
up_img = cv2.pyrUp(img)
#下采样
img2 = cv2.pyrDown(up_img)
#原图像与变换后的图像相减即为拉普拉斯金字塔
cv_show(img-img2,'laplacian')
运行结果:
主要参考于OpenCV官方网站:http://www.opencv.org.cn/
目前博主已更新OpenCV平滑处理函数、形态学操作函数的详细介绍,链接如下:
【OpenCV-图像处理】图像平滑处理函数
【OpenCV-图像处理】如何计算图像梯度,以及如何使用梯度来检测边缘
<后续还会继续翻译和整理【OpenCV-图像处理】相关内容,如果需要,可持续关注我哦~> |
<翻译和整理不易,留个赞或评论支持一下我吧^^>
如有疑问,欢迎批评指正^^