logo头像

猪老大要进步!

目标检测--滑动窗口算法的原理和实现

本文于 1231 天之前发表,文中内容可能已经过时。

滑动窗口算法作为最原始最简单的深度学习目标检测算法,容易上手并且原理简单,深受鄙人的喜爱。

本文将简单介绍滑动窗口算法的原理并且使用python实现它。

滑动窗口

原理

  • 首先选定一个特定大小的窗口,并使用以上的卷积神经网络判断这个窗口中有没有目标物体,滑动目标检测算法会从左上角向右并向下滑动输入窗口,并将截取的图像都输入到 已经训练好的卷积神经网络中 以固定步幅滑动窗口,遍历图像的每个区域

  • 然后使用比以上使用的窗口大一些的窗口,重复进行以上操作。然后再使用比上一次更大的窗口进行图像的截取与检测。

  • 所以无论目标在图像中的什么位置,总有一个窗口可以检测到它。

    img

缺点:

  • 但是滑动窗口目标检测算法有十分消耗计算成本的缺点,因为使用窗口会在原始图片中截取很多小方块,并且卷积神经网络需要一个个的进行处理。虽然使用较大的步长可以有效的节省计算成本,但是粗粒度的检测会影响性能,小步幅和小窗口就会大量的耗费计算成本
  • 早些时候在普通的线性分类器上使用滑动窗口目标检测算法可以有很好的性能,但是对于卷积神经网络这种对于图像识别相当耗费性能的算法而言,需要对滑动窗口算法进行重新设计。

实现

1. 载入需要的库

1
2
3
4
5
6
import numpy as np
import tensorflow as tf
import cv2import time
import matplotlib.pyplot as plt
from skimage.io import imread
from skimage.transform import resize

2. 神经网络的重载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
time_start = time.time()
saver=tf.train.import_meta_graph('./model/model.ckpt.meta')
sess=tf.Session()
sess.run(tf.compat.v1.global_variables_initializer())
saver.restore(sess, tf.train.latest_checkpoint('./model/'))
# 直接获取保存的变量
# 获取placeholder变量
input_x = sess.graph.get_tensor_by_name('x:0')
input_y = sess.graph.get_tensor_by_name('y:0')
keep_prob = sess.graph.get_tensor_by_name('keep_prob:0')
# 获取需要进行计算的operator
y_conv = sess.graph.get_tensor_by_name('y_conv:0')
time_end = time.time()
print('模型重载完成!耗时%ss'%str(time_end-time_start))

3. 滑动窗口的实现

据吴恩达口述,可以使用卷积的操作代替图片的切割, 卷积神经网络的滑动窗口实现提高了整个算法的效率。但是鄙人没能搞明白为什么以及怎么做,因此笔者还是采用了原始的图像切割方法。

  • 先读取图片
1
2
3
4
5
6
7
def load_image(path):    
img = imread(path)
img = resize(img,(900,900))
return img

path = '路径'
x_image = load_image(path,k)

将大图片分割成30x30的小图片,这里面大图片宽高最好是30的倍数,可以载入的时候先resize一下。上图像切割代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def fenge(image):    
#得到图片的高和宽
h,w,d = image.shape
small_img = np.zeros((int(h/30)*int(w/30),30,30,3))
#30x30图片分割
for i in range(int(h/30)):#行
for j in range(int(w/30)):#列
small_img[i*int(w/30)+j,:,:,:]=image[30*i:30*i+30,30*j:30*j+30,:]
small_img = small_img.astype(int)
return small_img

# 获取image的shape
h,w,d = x_image.shape
# 30x30图片分割
small_img = fenge(x_image)

原图的shape假设为(900,900,3),切割之后就变成了(900,30,30,3)

4. 小格子判别

图像切割完毕,现在需要对30x30的小格子进行识别。

  • 做出预测:
1
2
3
4
5
pred = sess.run(y_conv, {input_x: small_img,keep_prob:1.})
print(pred.shape)
print('预测完成!')
img_label = np.zeros(1080,dtype=np.int)
img_label = pred[:,0].astype(int)
  • 为存在目标的格子添加边框:
1
2
3
4
5
6
7
8
def add_bound(img):    
img = cv2.rectangle(img,(0,0),(29,29),(255,0,0),1)
return img

##加边框
for i in range(len(img_label)):
if img_label[i]==1:
small_img[i*30:i*30+30,:,:] = add_bound(small_img[i*30:i*30+30,:,:])

5. 重排图像并保存

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#small_img重排
for i in range(int(h/30)):#行
for j in range(int(w/30)):#列
x_image[30*i:30*i+30,30*j:30*j+30,:]=small_img[i*int(w/30)+j,:,:,:]

plt.rcParams['savefig.dpi'] = 300 #图片像素
plt.rcParams['figure.dpi'] = 100 #分辨率
plt.axis('off')
plt.imshow(x_image)
plt.savefig('judge.png',bbox_inches='tight',pad_inches=0.0)
#,dpi=300
plt.show()
print('图片存好了!')
# 关闭tf.session
sess.close()

6. 效果图

参考资料:

1、[DeeplearningAI笔记]卷积神经网络3.1-3.5目标定位/特征点检测/目标检测/滑动窗口的卷积神经网络实现/YOLO算法

支付宝打赏 微信打赏

赞赏是不耍流氓的鼓励