因为这几个月饭店生意恢复,加上研究 Faster-RCNN 用掉了很多时间,就没有更新博客了。这篇开始会介绍对象识别的模型与实现方法,首先会介绍最简单的 RCNN 与 Fast-RCNN 模型,下一篇会介绍 Faster-RCNN 模型,再下一篇会介绍 YOLO 模型。

图片分类与对象识别

在前面的文章中我们看到了如何使用 CNN 模型识别图片里面的物体是什么类型,或者识别图片中固定的文字 (即验证码),因为模型会把整个图片当作输入并输出固定的结果,所以图片中只能有一个主要的物体或者固定数量的文字。

如果图片包含了多个物体,我们想识别有哪些物体,各个物体在什么位置,那么只用 CNN 模型是无法实现的。我们需要可以找出图片哪些区域包含物体并且判断每个区域包含什么物体的模型,这样的模型称为对象识别模型 (Object Detection Model),最早期的对象识别模型是 RCNN 模型,后来又发展出 Fast-RCNN (SPPnet),Faster-RCNN ,和 YOLO 等模型。因为对象识别需要处理的数据量多,速度会比较慢 (例如 RCNN 检测单张图片包含的物体可能需要几十秒),而对象识别通常又要求实时性 (例如来源是摄像头提供的视频),所以如何提升对象识别的速度是一个主要的命题,后面发展出的 Faster-RCNN 与 YOLO 都可以在一秒钟检测几十张图片。

对象识别的应用范围比较广,例如人脸识别,车牌识别,自动驾驶等等都用到了对象识别的技术。对象识别是当今机器学习领域的一个前沿,2017 年研发出来的 Mask-RCNN 模型还可以检测对象的轮廓。

因为看上去越神奇的东西实现起来越难,对象识别模型相对于之前介绍的模型难度会高很多,请做好心理准备。

对象识别模型需要的训练数据

在介绍具体的模型之前,我们首先看看对象识别模型需要什么样的训练数据:

对象识别模型需要给每个图片标记有哪些区域,与每个区域对应的标签,也就是训练数据需要是列表形式的。区域的格式通常有两种,(x, y, w, h) => 左上角的坐标与长宽,与 (x1, y1, x2, y2) => 左上角与右下角的坐标,这两种格式可以互相转换,处理的时候只需要注意是哪种格式即可。标签除了需要识别的各个分类之外,还需要有一个特殊的非对象 (背景) 标签,表示这个区域不包含任何可以识别的对象,因为非对象区域通常可以自动生成,所以训练数据不需要包含非对象区域与标签。

RCNN

RCNN (Region Based Convolutional Neural Network) 是最早期的对象识别模型,实现比较简单,可以分为以下步骤:

  • 用某种算法在图片中选取 2000 个可能出现对象的区域
  • 截取这 2000 个区域到 2000 个子图片,然后缩放它们到一个固定的大小
  • 用普通的 CNN 模型分别识别这 2000 个子图片,得出它们的分类
  • 排除标记为 "非对象" 分类的区域
  • 把剩余的区域作为输出结果

你可能已经从步骤里看出,RCNN 有几个大问题:

  • 结果的精度很大程度取决于选取区域使用的算法
  • 选取区域使用的算法是固定的,不参与学习,如果算法没有选出某个包含对象区域那么怎么学习都无法识别这个区域出来
  • 慢,贼慢,识别 1 张图片实际等于识别 2000 张图片

后面介绍模型结果会解决这些问题,但首先我们需要理解最简单的 RCNN 模型,接下来我们细看一下 RCNN 实现中几个重要的部分吧。

选取可能出现对象的区域

选取可能出现对象的区域的算法有很多种,例如滑动窗口法 (Sliding Window) 和选择性搜索法 (Selective Search)。滑动窗口法非常简单,决定一个固定大小的区域,然后按一定距离滑动得出下一个区域即可。滑动窗口法实现简单但选取出来的区域数量非常庞大并且精度很低,所以通常不会使用这种方法,除非物体大小固定并且出现的位置有一定规律。

选择性搜索法则比较高级,以下是简单的说明,摘自 opencv 的文章

你还可以参考 这篇文章原始论文 了解具体的计算方法。

如果你觉得难以理解可以跳过,因为接下来我们会直接使用 opencv 类库中提供的选择搜索函数。而且选择搜索法精度也不高,后面介绍的模型将会使用更好的方法。

# 使用 opencv 类库中提供的选择搜索函数的代码例子
import cv2 img = cv2.imread("图片路径")
s = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
s.setBaseImage(img)
s.switchToSelectiveSearchFast()
boxes = s.process() # 可能出现对象的所有区域,会按可能性排序
candidate_boxes = boxes[:2000] # 选取头 2000 个区域

按重叠率 (IOU) 判断每个区域是否包含对象

使用算法选取出来的区域与实际区域通常不会完全重叠,只会重叠一部分,在学习的过程中我们需要根据手头上的真实区域预先判断选取出来的区域是否包含对象,再告诉模型预测结果是否正确。判断选取区域是否包含对象会依据重叠率 (IOU - Intersection Over Union),所谓重叠率就是两个区域重叠的面积占两个区域合并的面积的比率,如下图所示。

我们可以规定重叠率大于 70% 的候选区域包含对象,重叠率小于 30% 的区域不包含对象,而重叠率介于 30% ~ 70% 的区域不应该参与学习,这是为了给模型提供比较明确的数据,使得学习效果更好。

计算重叠率的代码如下,如果两个区域没有重叠则重叠率会为 0:

def calc_iou(rect1, rect2):
"""计算两个区域重叠部分 / 合并部分的比率 (intersection over union)"""
x1, y1, w1, h1 = rect1
x2, y2, w2, h2 = rect2
xi = max(x1, x2)
yi = max(y1, y2)
wi = min(x1+w1, x2+w2) - xi
hi = min(y1+h1, y2+h2) - yi
if wi > 0 and hi > 0: # 有重叠部分
area_overlap = wi*hi
area_all = w1*h1 + w2*h2 - area_overlap
iou = area_overlap / area_all
else: # 没有重叠部分
iou = 0
return iou

原始论文

如果你想看 RCNN 的原始论文可以到以下的地址:

https://arxiv.org/pdf/1311.2524.pdf

使用 RCNN 识别图片中的人脸

好了,到这里你应该大致了解 RCNN 的实现原理,接下来我们试着用 RCNN 学习识别一些图片。

因为收集图片和标记图片非常累人

写给程序员的机器学习入门 (九) - 对象识别 RCNN 与 Fast-RCNN的更多相关文章

  1. 写给程序员的机器学习入门 (十) - 对象识别 Faster-RCNN - 识别人脸位置与是否戴口罩

    每次看到大数据人脸识别抓逃犯的新闻我都会感叹技术发展的太快了,国家治安水平也越来越好了

  2. 写给程序员的机器学习入门 (十一) - 对象识别 YOLO - 识别人脸位置与是否戴口罩

    这篇将会介绍目前最流行的对象识别模型 YOLO,YOLO 的特征是快,识别速度非常快

  3. 写给程序员的机器学习入门 (八 补充) - 使用 GPU 训练模型

    在之前的文章中我训练模型都是使用的 CPU,因为家中黄脸婆不允许我浪费钱买电脑.终于的,附近一个废品回收站的朋友转让给我一台破烂旧电脑,所以我现在可以体验使用 GPU 训练模型了

  4. 写给程序员的机器学习入门 (二) - pytorch 与矩阵计算入门

    pytorch 简介 pytorch 是目前世界上最流行的两个机器学习框架的其中之一,与 tensoflow 并峙双雄.它提供了很多方便的功能,例如根据损失自动微分计算应该怎样调整参数,提供了一系列的 ...

  5. 写给程序员的机器学习入门 (五) - 递归模型 RNN,LSTM 与 GRU

    递归模型的应用场景 在前面的文章中我们看到的多层线性模型能处理的输入数量是固定的,如果一个模型能接收两个输入那么你就不能给它传一个或者三个.而有时候我们需要根据数量不一定的输入来预测输出,例如文本就是 ...

  6. 写给程序员的机器学习入门 (七) - 双向递归模型 (BRNN) - 根据上下文补全单词

    这一篇将会介绍什么是双向递归模型和如何使用双向递归模型实现根据上下文补全句子中的单词. 双向递归模型 到这里为止我们看到的例子都是按原有顺序把输入传给递归模型的,例如传递第一天股价会返回根据第一天股价 ...

  7. 写给程序员的机器学习入门 (八) - 卷积神经网络 (CNN) - 图片分类和验证码识别

    这一篇将会介绍卷积神经网络 (CNN),CNN 模型非常适合用来进行图片相关的学习,例如图片分类和验证码识别,也可以配合其他模型实现 OCR. 使用 Python 处理图片 在具体介绍 CNN 之前, ...

  8. Java程序员的Golang入门指南(下)

    Java程序员的Golang入门指南(下) 4.高级特性 上面介绍的只是Golang的基本语法和特性,尽管像控制语句的条件不用圆括号.函数多返回值.switch-case默认break.函数闭包.集合 ...

  9. Java程序员的Golang入门指南(上)

    Java程序员的Golang入门指南 1.序言 Golang作为一门出身名门望族的编程语言新星,像豆瓣的Redis平台Codis.类Evernote的云笔记leanote等. 1.1 为什么要学习 如 ...

随机推荐

  1. 在嵌入式设备中实现webrtc的第三种方式①

    最近两年,我对于网络知识,包括底层协议学习比较多,webrtc这种几乎是使用到了所有层面网络协议的技术也逐渐进入我的视野. 之前我提出了两种在嵌入式设备上实现webrtc的方式,一是用官方代码,然后改 ...

  2. 一起学Vue:CRUD(增删改查)

    目标 使用Vue构建一个非常简单CRUD应用程序,以便您更好地了解它的工作方式. 效果页面 比如我们要实现这样列表.新增.编辑三个页面: 列表页面 新增页面 编辑页面 我们把这些用户信息保存到Todo ...

  3. 【总结】nginx基础

    一.nginx简介 1.什么是nginx? Nginx 是高性能的 HTTP 和反向代理的服务器,处理高并发能力是十分强大的,支持高达 50,000 个并发连接数.功能:反向代理,负载均衡,动静分离 ...

  4. 从原生web组件到框架组件源码(一)

    温馨提醒,当你觉得看我写的很乱的时候,就对了,那是因为我查阅了大量的资料提取出来的,因为有点东西不太理解,所以你会感觉有的部分重复了,也不是重复,只是后面对前面的内容进行梳理了一些,需要耐心的看到最后 ...

  5. 工业级4G路由器有哪些优势

    在金融.电力.邮政以及气象等各大行业中有着更为广泛的应用,并受到人们的高度推崇与青睐,那么工业级4G路由器有哪些优势深受用户的喜欢呢? 1.高稳定性 工业级4G路由器在传输和接收数据时具有较高的稳定性 ...

  6. MYSQL中inner join、left join 和 right join的区别

    首先join连接是用来进行多表关联查询的,join连接方式有三种连接方式:inner join.left join 和 right join 1.inner join 可以简写成join,叫内连接,查 ...

  7. git使用心得体会

    序言:身为软件工程的学生却一直没有接触Git,实在有些羞愧.得益于孟宁老师的课程,让我对Git有了初步的认识.同样借由此次机会正式接触Git这款程序员必备工具. 参考文献:https://mp.wei ...

  8. 服务器性能监控神器nmon使用介绍

    介绍 Nmon (Nigel's Monitor)是由IBM 提供.免费监控 AIX 系统与 Linux 系统资源的工具.该工具可将服务器系统资源耗用情况收集起来并输出一个特定的文件,并可利用 exc ...

  9. Java8 新特性 —— 函数式编程

    本文部分摘录自 On Java 8 概述 通常,传递给方法的数据不同,结果也不同.同样的,如果我们希望方法被调用时的行为不同,该怎么做呢?结论是:只要能将代码传递给方法,那么就可以控制方法的行为. 说 ...

  10. 无法将“add-migration”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。解决方案

    在程序包管理控制台中执行 Install-Package Microsoft.EntityFrameworkCore.Tools