目标检测实践(1)–滑动窗口

王 茂南 2024年12月1日07:51:45
评论
2576字阅读8分35秒

简介

从本篇文章开始,我们会开始介绍目标检测相关的知识。所谓目标检测,就是让计算机能够识别图片中的目标(物体、动物等)是什么、这个目标的位置在哪里。

如下图所示,通过检测算法,我们可以找出目标是什么,以及具体的坐标:

 

目标检测的主要有下面的两大类方法:

  • 传统检测算法
    • 将人为设计的目标特征和机器学习的分类器相结合来实现的
  • 基于深度学习的检测算法(共有下面两种)
    • 基于候选区域(Region Proposal)的方法先找出图片中可能存在目标的区域,然后通过卷积神经网络对该区域进行分类;
    • 另一类是直接使用卷积神经网络预测目标所属类别的概率和其在图片中的位置坐标;

传统检测算法

下面我们来详细说一下「传统检测算法」的步骤:

  • 给定一张待检测的图片;
  • 使用滑动窗口(Sliding Windows)图像金字塔(Image Pyramid)两种方法,从图片中选择区域;
  • 通过一些算法提取这些区域的特征信息(例如梯度直方图);
  • 使用机器学习的方法,结合区域的特征信息来进行分类;
  • 使用非极大值抑制(Non-maxima suppression)来剔除多余的矩形框,确保每个目标只用一个矩形框标记。(使用滑动窗口和图像金字塔时会在同一个目标上会标记出多个矩形框,因此需要剔除多余的框)

上面提到的所有内容,我们会在后面逐一进行介绍。本文会首先对「滑动窗口」进行介绍。

 

滑动窗口介绍

滑动窗口是什么

滑动窗口(Sliding Windows)在目标检测过程中的作用是定位目标(物体、动物等)在图片中的位置。在计算机视觉中滑动窗口是一个矩形框,它沿着从左向右、从上向下的方向在图片上滑动以达到提取出图片中每一个区域的目的。

下图就是一个滑动窗口的例子,可以看到一个绿色矩形框沿着从左向右、从上向下的方向在图片上滑动。对于矩形框滑过的每一区域,我们使用分类器来判断该区域中是否存在物体。

目标检测实践(1)–滑动窗口

实现滑动窗口

上面我们介绍了什么是滑动窗口。下面我们来实现滑动窗口的功能。我们首先导入需要使用到的库:

  1. import cv2
  2. from matplotlib import pyplot as plt
  3. from IPython import display
  4. %matplotlib inline
然后我们定义一个函数 sliding_window 用于获取滑动窗口。每次可以返回当前这个矩形在原始图片的位置,并返回矩形部分的图像内容。
  1. def sliding_window(image, window, step):
  2.     """矩形框遍历原始图像, 返回矩形框所在位置, 和矩形框内的图像
  3.     """
  4.     for y in range(0, image.shape[0] - window[1], step):
  5.         for x in range(0, image.shape[1] - window[0], step):
  6.             yield (x, y, image[y:y + window[1], x:x + window[0]])
上面的函数有三个参数 imagewindow 和 step
  • 第一个参数 image 是输入函数的图片,我们将用矩形框在这个图片上滑动。
  • 第二个参数 window 是一个元组,表示滑动的矩形框的高和宽。
  • 第三个参数 step 表示矩形框间隔多少个像素移动一次,这里我们可以称之为步长一般而言步长的选择是 4 到 8 像素之间。
我们随意导入一张图片,之后用来测试「滑动窗口」的效果。导入图片的代码如下所示:
  1. # 导入图像
  2. image = cv2.imread("./image/class_one/pets.png")
  3. image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
  4. # 用于图像的显示
  5. fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(7,7))
  6. axes.axis("off")
  7. axes.imshow(image)
这里输出结果如下所示(因为在 OpenCV 图片是以 BGR(蓝,绿,红)的通道顺序存储的,而在 Matplotlib 中图片是以 RGB 的通道顺序存储,所以需要使用 cvtColor 进行转换): 接下来我们来遍历每一个滑动窗口。在这里我们为了方便演示,将步长设置为 100 像素,但是在实际使用中不建议设置太大或是太效,设置 48 会比较合适。 在遍历的时候,有下面两点需要注意:
  • 首先需要判断截取的窗口大小是否与矩形框一样,会在图片的边边部分出现问题。
  • 为了可以动态显示,我们需要每次复制原始图像,因为每次会在原始图片上进行修改,在原始图片上增加矩形框。
下面是实现滑动窗口的代码,通过上面定义的 sliding_window 函数,每次返回矩形的坐标,我们在原始图像上绘制矩形,并将矩形框内的图像进行保存:
  1. # 定义滑动窗口的大小
  2. (window_w, window_h) = (128, 128)
  3. for (x, y, window) in sliding_window(image, (window_w, window_h), 100):
  4.     if window.shape[0] != window_w or window.shape[1] != window_h: # 判断截取的窗口与矩形框的大小是否一样
  5.         continue
  6.     cv2.imwrite('./image/class_one/sliding/x_{}_y_{}.png'.format(x, y), cv2.cvtColor(window, cv2.COLOR_RGB2BGR)) # 保存图像
  7.     clone = image.copycopy() # 需要复制原始图片, 因为会修改原始图片, 在上面画框
  8.     cv2.rectangle(clone, (x, y), (x + window_w, y + window_h), (0, 255, 0), 2) # 在图片上绘制矩形
  9.     plt.imshow(clone)
  10.     plt.pause(0.1)
  11.     display.clear_output(wait=True)

于是最终的滑动窗口的效果如下图所示:

目标检测实践(1)–滑动窗口

同时我们将每次矩形区域的小图都保存下来,会有如下所示的效果:

目标检测实践(1)–滑动窗口

  • 微信公众号
  • 关注微信公众号
  • weinxin
  • QQ群
  • 我们的QQ群号
  • weinxin
王 茂南
  • 本文由 发表于 2024年12月1日07:51:45
  • 转载请务必保留本文链接:https://mathpretty.com/13707.html
匿名

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: