如何使用Faster R-CNN来计算对象个数
2017年08月19日 由 yining 发表
98784
0
准确地在给定的图像或视频帧中计算对象个数的实例是机器学习中很难解决的问题。尽管许多解决方案已经被开发出来,用来计算人、汽车和其他物体的数量,但是没有一个是完美的办法。当然,我们这里讨论的是图像处理,所以神经网络对于这项工作来说似乎是一个很好的工具。
你可以在下面的神经网络对象计数域中找到不同方法、常见问题、挑战和最新解决方案的描述。作为概念的证明,Faster R-CNN网络的现有模型将被用来计算街道上的物体数量,并在文章的最后给出视频示例。
挑战
对于计算对象个数的问题,找到一个合适的解决方案取决于许多因素。除了一些与神经网络图像处理有关的挑战,例如训练数据的大小,它的质量等等。下面是对计数对象个数问题的具体挑战:
- 要计算的对象类型
- 重叠
- 透视图
- 检测到的对象的最小尺寸
- 训练和测试速度
用来计算公路上的汽车数量或是体育场上的人群的这些方法,通常大多数对象重叠,并且透视图通常也是允许遥远距离中很小的对象的。
同时,在一个单一图片中计算对象数量的解决方案可以不同于在一个实时视频中计算对象数量的解决方案。
简单的需求,简单的解决方案
在这篇文章中,我将尝试解决在街道上计算对象数量的问题,使用多个对象同时可见的示例视频。为了处理拥挤场景的图像或交通堵塞,以准确地计算物体数量的实例,我建议深入研究该领域的最新研究:“
Towards perspective-free object counting with deep learning(利用深度学习进行无透视对象的数量计算)”。这篇论文的结果可以用GitHub上的
代码进行复制。
在上述的论文中,像CCNN和Hydra CNN这样的方法在给定不同类型的对象的情况下表现不佳,因此需要采取不同的方法。
在机器学习领域(特别是卷积神经网络的深度学习)中,有一种非常有趣的方法,叫做基于区域的卷积神经网络(R-CNN),我们可以在一个给定的图像上识别多个物体及其位置。
为了我们的概念验证工作,我将使用“Faster R-CNN”的
Keras实现来处理视频文件,并使用给定类的检测对象来对图像进行注释。
FAST和FASTER
有许多方法可以把找到对象位置和识别对象的方法结合起来,以提高速度和准确性。多年来,我们已经从使用标准的RCNN网络,通过Fast R-CNN,到Faster R-CNN,来解决我们简单的计算问题。 Fast R-CNN建立在之前的工作上,以有效地利用深度卷积网络对对象提议进行分类。与R-CNN相比,Fast R-CNN引入了一些改进训练和测试速度的创新,以及检测的准确性。
在多阶段管道(multi-stage pipelines)中使用R-CNN训练模型的方法(首先检测对象边界,然后执行识别)是相当慢的,不适合实时处理。这种方法的缺点主要是它的速度,无论是在训练过程中,还是在实际测试期间。当对象检测被执行的时候,
使用著名的
VGG16,一个标准的R-CNN的训练过程:GPU需要花费两天半的时间来完成5000张的图像,并且需要几百GB的存储空间。在测试时检测对象使用一个GPU来花费47s处理出一张图片。这主要是由于在没有共享计算的情况下,对每个对象提议进行了卷积网络的正向传递。
Fast R-CNN通过引入一种单阶段训练算法来改进R-CNN,该算法将对象和它们的空间位置在一个处理阶段进行分类。Fast R-CNN的改进是:
- 更高的检测质量
- 在单一阶段使用多任务损失进行训练
- 训练可以更新所有网络层
- 特性缓存不需要磁盘存储
Faster R-CNN引入了一个区域提议网络(RPN),它与检测网络共享完整图像的卷积特性,支持几乎没有成本的区域建议。这个解决方案的RPN组件指出了统一的网络在哪里可以查看。对于同样的VGG-16模型, Faster R-CNN在GPU上的帧速率为5 fps,同时达到了最先进的目标检测精度。RPN是一种完全的卷积网络,可以针对生成检测方案的任务进行端到端训练,并被设计用来有效地预测具有广泛范围和纵横比的区域提议。
Faster R-CNN在去年被
Pinterest用作一种解决方案,可以在他们的网站上进行视觉搜索,可以在下面的PoC描述中看到我们检测和计算样本视频中的对象。
概念验证
为了解决我们的想象问题,我们将使用前面提到的Faster R-CNN模型,和在一个GPU可行的AWS实例上的Keras。我们处于一个舒适的位置,可以下载已经预先训练好的模型,最适合我们的需求和选择的框架。当然,你可以使用所提供的Python脚本对模型进行训练,请记住,它可能需要花费许多时间。
对于Faster R-CNN来说,它存在多重实现,包括
Caffe,
TensorFlow等等。我们将在后端使用TensorFlow和Keras(v.2.0.3)。这段代码可以作为
GitHub上最初的Keras F R-CNN实现的一个复刻(fork)。
测试网络的脚本被修改,这样它就可以处理视频文件,并为检测到的对象(有可能性)添加适当的数据,并对已计数对象的摘要进行注释。我使用opencv来处理视频和已经训练过的模型(可在这里
下载),同时处理帧。
有许多用于处理视频的实用方法,例如:
def convert_to_images():
cam = cv2.VideoCapture(input_video_file)
counter = 0
while True:
flag, frame = cam.read()
if flag:
cv2.imwrite(os.path.join(img_path, str(counter) + '.jpg'),frame)
counter = counter + 1
else:
break if cv2.waitKey(1) == 27:
break
# press esc to quit
cv2.destroyAllWindows()
并将视频从经过处理的帧中保存:
def save_to_video():
list_files = sorted(get_file_names(output_path), key=lambda var:[int(x) if x.isdigit() else x for x in re.findall(r'[^0-9]|[0-9]+', var)])
img0 = cv2.imread(os.path.join(output_path,'0.jpg'))
height , width , layers = img0.shape
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
videowriter = cv2.VideoWriter(output_video_file,fourcc, frame_rate, (width,height))
for f in list_files:
print("saving..." + f)
img = cv2.imread(os.path.join(output_path, f)) videowriter.write(img)
videowriter.release()
cv2.destroyAllWindows()
当对象检测在测试期间进行时,我正在创建一个带有检测对象类和第1号的元组列表,这一列表在之后会减少为特定对象类的出现次数:
for jk in range(new_boxes.shape[0]):
(x1, y1, x2, y2) = new_boxes[jk,:]
cv2.rectangle(img_scaled,(x1, y1), (x2, y2), class_to_color[key],2)
textLabel = '{}: {}'.format(key,int(100*new_probs[jk]))
all_dets.append((key,100*new_probs[jk]))
all_objects.append((key, 1))
减少的方法:
def accumulate(l):
it = itertools.groupby(l, operator.itemgetter(0))
for key, subiter in it:
yield key, sum(item[1] for item in subiter)
脚本参数是自描述型的
- "--input_file",输入视频文件的路径。
- "--output_file",输出视频文件的路径。
- "--input_dir", 输入工作目录的路径,在该目录中存储了经过处理的帧。
- "--output_dir" 路径到输出工作目录,其中有带注释的处理框架存储。
- "--frame_rate" 帧率在构建视频输出时使用帧率。
使用示例:
python test_frcnn_count.py
脚本处理的几个例子:
视频片段地址:
https://www.youtube.com/watch?v=z2wQBNDYRXg
https://www.youtube.com/watch?v=n4vQxAFncKA
https://www.youtube.com/watch?v=YqoGPpFfQiA
相关链接和下载