写给程序员的机器学习入门 (九) - 对象识别 RCNN 与 Fast-RCNN
因为这几个月饭店生意恢复,加上研究 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的更多相关文章
- 写给程序员的机器学习入门 (十) - 对象识别 Faster-RCNN - 识别人脸位置与是否戴口罩
每次看到大数据人脸识别抓逃犯的新闻我都会感叹技术发展的太快了,国家治安水平也越来越好了
- 写给程序员的机器学习入门 (十一) - 对象识别 YOLO - 识别人脸位置与是否戴口罩
这篇将会介绍目前最流行的对象识别模型 YOLO,YOLO 的特征是快,识别速度非常快
- 写给程序员的机器学习入门 (八 补充) - 使用 GPU 训练模型
在之前的文章中我训练模型都是使用的 CPU,因为家中黄脸婆不允许我浪费钱买电脑.终于的,附近一个废品回收站的朋友转让给我一台破烂旧电脑,所以我现在可以体验使用 GPU 训练模型了
- 写给程序员的机器学习入门 (二) - pytorch 与矩阵计算入门
pytorch 简介 pytorch 是目前世界上最流行的两个机器学习框架的其中之一,与 tensoflow 并峙双雄.它提供了很多方便的功能,例如根据损失自动微分计算应该怎样调整参数,提供了一系列的 ...
- 写给程序员的机器学习入门 (五) - 递归模型 RNN,LSTM 与 GRU
递归模型的应用场景 在前面的文章中我们看到的多层线性模型能处理的输入数量是固定的,如果一个模型能接收两个输入那么你就不能给它传一个或者三个.而有时候我们需要根据数量不一定的输入来预测输出,例如文本就是 ...
- 写给程序员的机器学习入门 (七) - 双向递归模型 (BRNN) - 根据上下文补全单词
这一篇将会介绍什么是双向递归模型和如何使用双向递归模型实现根据上下文补全句子中的单词. 双向递归模型 到这里为止我们看到的例子都是按原有顺序把输入传给递归模型的,例如传递第一天股价会返回根据第一天股价 ...
- 写给程序员的机器学习入门 (八) - 卷积神经网络 (CNN) - 图片分类和验证码识别
这一篇将会介绍卷积神经网络 (CNN),CNN 模型非常适合用来进行图片相关的学习,例如图片分类和验证码识别,也可以配合其他模型实现 OCR. 使用 Python 处理图片 在具体介绍 CNN 之前, ...
- Java程序员的Golang入门指南(下)
Java程序员的Golang入门指南(下) 4.高级特性 上面介绍的只是Golang的基本语法和特性,尽管像控制语句的条件不用圆括号.函数多返回值.switch-case默认break.函数闭包.集合 ...
- Java程序员的Golang入门指南(上)
Java程序员的Golang入门指南 1.序言 Golang作为一门出身名门望族的编程语言新星,像豆瓣的Redis平台Codis.类Evernote的云笔记leanote等. 1.1 为什么要学习 如 ...
随机推荐
- 关于oracle监听程序的相关问题及解决方法
1.查看监听程序是否启动 打开cmd窗口,cmd用管理员运行,否则无法执行启动与停止监听命令 lsnrctl status查看运行状态 lsnrctl stop停止监听 lsnrctl start启动 ...
- STM32入门系列-存储器与寄存器介绍
介绍两部分内容: 什么是存储器映射 什么是寄存器及寄存器映射 为了让大家对存储器与寄存器有一个更清楚的认识,并且为之后使用 C 语言来访问 STM32 寄存器内容打下基础.等明白了如何使用 C 语言封 ...
- SpringBoot整合Logback日志框架配置全解析
目录 本篇要点 一.Logback日志框架介绍 二.SpringBoot与Logback 1.默认日志格式 2.控制台输出 3.文件输出 4.日志级别 5.日志组 6.自定义log配置 三.logba ...
- git 上传代码报错eslint --fix found some errors. Please fix them and try committing again.
在提交时用下面这句 git commit --no-verify -m "提交时的注释"
- modbus协议开关量采集模块
modbus协议开关量采集模块是指的使用Modbus协议的进行信号的采集与控制的一种设备. Modbus 协议设备都具有唯一的 Modbus 地址,众山 DTU 默认 Modbus 地址为 100,用 ...
- [LuoguP1005]矩阵取数游戏 (DP+高精度)
题面 传送门:https://www.luogu.org/problemnew/show/P1005 Solution 我们可以先考虑贪心 我们每一次都选左右两边尽可能小的数,方便大的放在后面 听起来 ...
- React react-redux props或state更新视图无法重新渲染问题
记录学习React时自己是如何挖坑把自己埋了的过程:children以及其它props被修改时相关组件无法重新渲染(做了两天) 父组件代码: class UserHome extends Compon ...
- 解决windows下Chrome78以上跨域失效问题
1. 为什么需要解决chrome浏览器跨域的问题? 基于Hybird App的H5部分,可以直接打包进apk或者ipa包中,在开发过程中也不需要放置到临时搭建的服务器上,直接在本地打开html静态页面 ...
- pytorch训练GAN时的detach()
我最近在学使用Pytorch写GAN代码,发现有些代码在训练部分细节有略微不同,其中有的人用到了detach()函数截断梯度流,有的人没用detch(),取而代之的是在损失函数在反向传播过程中将bac ...
- 为研发同学定制的MySQL面试指南 - “能谈谈基数统计吗?”
** 目录 推荐阅读原文链接 一.基数是啥? 二.InnoDB更新基数的时机? 三.基数是估算出来 四.持久化基数 四.如何主动更新基数? 欢迎关注 Hi,大家好!我是白日梦. 今天我要跟你分享的话题 ...