使用Python和OpenCV的图像金字塔
这篇博客将介绍如何使用两种方法构造图像金字塔。
-
使用Python和OpenCV构建金字塔,此方法不会在金字塔的每一层使用高斯平滑图像,因此更适合与HOG描述符一起使用。
-
使用Python + scikit-image构建金字塔,在金字塔的每一层都应用高斯平滑。
应该使用哪种方法?——取决于应用程序。如果将HOG描述符用于对象分类,则使用第一种方法,因为平滑会损害分类性能。
如果要实施SIFT或高斯差分关键点检测器之类的方法,则使用第二种方法(或至少将平滑方法纳入第一种方法)。
1. 效果图
法一:未进行高斯平滑的金字塔效果图:
使用高斯平滑的图像金字塔效果图如下:可能因为scikit-image版本 0.17.1原因,不支持彩色图~~
可以看到高斯平滑的金字塔比不使用高斯平滑的级别少,这是因为高斯平滑的以1/2层级降,更快;
当设置不同的scale级别时,俩种方式能生成的级别也不一致,可以尽情试试。
2. 什么是图像金字塔?
如上图所示,图像金字塔”是图像的多尺度表示。最下面的图拥有原始的图像宽度、高度,每上一层,图像的宽度与高度分别为之前的一半,并且进行了高斯平滑模糊等操作。
利用图像金字塔,可以在图像的不同比例下找到图像中的对象。当与滑动窗口结合使用时,可以在各个位置的图像中找到对象。
在金字塔的底部是原始图像的原始大小(宽度和高度)。并在每个随后的层上调整图像大小(二次采样)并可选地平滑(通常通过高斯模糊)。
逐步对图像进行二次采样,直到满足某个停止标准为止,该标准通常已达到最小尺寸,并且无需进行进一步的二次采样。
通常,性能和生成的层数之间需要权衡。比例因子越小,则需要创建和处理的图层就越多-但这也使图像分类器有更好的机会定位要在图像中检测的对象。
较大的比例因子将产生较少的图层,并且可能会损害对象的分类性能。但是,由于要处理的层数较少,因此可以获得更高的性能。
3. 依赖
- imutils
- scikit-image 安装可参考
4. 源码
# 图像金字塔的俩种方法
# USAGE
# python pyramid.py --image images/_L3A4387.jpg --scale 1.5
# 导入必要的包
import argparse
import imutils
import cv2
from skimage.transform import pyramid_gaussian # 导入scikit图像pyramid_gaussian函数
# 构建金字塔
# - minSize 图层所需的最小宽度和高度
def pyramid(image, scale=1.5, minSize=(30, 30)):
# 产生原始图像
yield image
# 保持循环金字塔模式
while True:
# 计算图像新的规模大小,并保留宽高比的缩放图像
w = int(image.shape[1] / scale)
image = imutils.resize(image, width=w)
# 如果金字塔中的图像低于此最小尺寸,将不再构建图像金字塔
# 停止循环
if image.shape[0] < minSize[1] or image.shape[1] < minSize[0]:
break
# 产生金字塔的下一张图像
yield image
# 构建命令行参数及解析
# --image 原始图像路径
# --scale 控制在金字塔中调整图像大小的比例因子
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="Path to the image")
ap.add_argument("-s", "--scale", type=float, default=1.5, help="scale factor size")
args = vars(ap.parse_args())
# 加载图像
image = cv2.imread(args["image"])
image = imutils.resize(image, width=800)
# 法一: 不平滑,只是缩放图像
# 遍历图像金字塔
for (i, resized) in enumerate(pyramid(image, scale=args["scale"])):
# 展示金字塔图像结果
cv2.imshow("Layer {}".format(i + 1), resized)
cv2.waitKey(0)
# 关闭所有打开的窗口
cv2.destroyAllWindows()
# 法二: 缩放+高斯平滑
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
for (i, resized) in enumerate(pyramid_gaussian(image, downscale=2)):
# 如果图像太小,则停止缩放
if resized.shape[0] < 30 or resized.shape[1] < 30:
break
# 展示金字塔图像结果
cv2.imshow("pyramid_gaussian Layer {}".format(i + 1), resized)
cv2.waitKey(0)