以前学习时收藏的资料,整理电脑,放在此处,以备后用
何为 YOLO(You Only Look Once)
YOLO [点击] 充满青春暗示的另一面,更是一个强大物体检测算法的简称,其算法结合了速度与准确度,近期更推出了第三版的 model 供大家参考,大幅度提升了前一版的性能。作者为一位资深 computer scientist: Joseph Chet Redmon 精通数据科学,编程等工作,与另外四名伙伴一同开发了此模型。
与以往的重复定位不同图片区域,并多次加权算出最高的得分区域来衡量该物体的属性与位置不同,YOLO 采用了一次性的神经网络层,直接平行分析图片中每个区域的各种可能,并在可能性最大的区域画出一个方框后标记方框内的物体对应的属性。这样的流程大幅提升准确度和计算速度,击败诸多先前模型的 performance。更详细的描述可以参考此篇文章 [点击]。
我作为一个计算机小白出身的光学工程师,学习之路走到今天能用上大神推行出来的物体检测算法来应用到自己的电脑上,已经是无比激动的一件事情了。从 Python 代码的编写学习,到模块包应用如:os, re, bs4, math, urllib, cv2, numpy, moviepy, ... 等等,再跳到现在的综合考验环节,做出自己设定结果的瞬间,只想感谢强大的万维网提供如此之完备的资源能够让一个人独立完成所有工作。一方面为了加深自己对此领域的记忆,一方面也希望自己淌过的坑可以说出来和大家分享,让同为这方面的爱好者有个前车之鉴,但是本人资历尚浅,要是描述中有何不妥也衷心感谢大神们的回馈!
实时物体检测的主要三环节
- 搜集数据
面对成千上万的物体种类与名称,必须预先搜集我们期望机器了解的种类的图像数据,通常需要上千张类似的图片作为资料库,面对庞大的量我们将会选择使用简单爬虫的方法,利用常见的搜寻引擎如 Google 或是 Baidu 作为主要手段。 - 标记数据
搜集好数据后,接下来的步骤就是手把手的教导机器 “什么是什么” 环节。面对每张涵盖了相关信息内容的图片,我们将基于这些图片生成一个 xml 文档来记录相关物体的坐标信息,并以此 xml 文档与对应图片作为输入要件,进入到下一个步骤。 - 训练模型
下载好相关的 YOLO 文件(它们都是检测算法里面重要的部件),并在 Terminal 或是 CMD 里面告诉计算机前面两个环节生成好的文件所在路径,最后开始让计算机去根据我们搜集来的数据训练,等到 Loss Value 降低到一个极限的时候,基本上就可以认定它被训练好了,并可以作为一个更新的模型辨认出我们希望它辨认的物体。
Data Collecting 搜集数据
于实战中使用到的 Python module 有:(模块引用名: 使用文档)
- urllib: https://docs.python.org/3/library/urllib.html
- re: https://docs.python.org/3/library/re.html
- os: https://docs.python.org/3/library/os.html
- json: https://docs.python.org/3/library/json.html
- numpy: https://docs.scipy.org/doc/numpy-1.11.0/numpy-user-1.11.0.pdf
- bs4: https://media.readthedocs.org/pdf/beautiful-soup-4/latest/beautiful-soup-4.pdf
p.s. 更多记录会逐一完备并添加链接于此,更为深入的介绍个人使用每个包的心得与常见功能
The codes are written below in practice:
设计代码的时候,python 环境中的我们同样倾向于模块化的功能编写,这样不仅写出来的代码逻辑性强,如果模块的名字取得好,那写出来的代码就可以说是超级易懂的了。整体代码步骤如下:
- 引入需要用到的模块
- 为了防止网站反爬虫机制,做一个头档(hd)去伪装自己像是个浏览器
- 使用 “图片” 搜寻引擎的 API 作为网址(如果直接去图片搜寻的网页把其 URL 拷贝也是可以,只是效率低下,原因稍后说明)
- 定义第一个功能函数 google_get_links(keyword) ,拿一个关键词作为输入,以 google 搜寻作为手段输出一个装满相关图片网址的 list,同样的逻辑适用于函数 baidu_get_links(keyword)
- 定义第三个功能函数 save_images(links_list, keyword) 用来下载前面函数找下来一箩筐的图片网址,把这些图片网址下载成图片存到本地指定的新建资料夹位置,并以 keyword 关键词作为新建资料夹的命名
但是深究其中代码会发现,google_get_links 和 baidu_get_links 里面的运作机制不同,原因就差在 API 上面,特别把不用 baidu API [点击] 的代码写出来对比缺点。API 就像一个该网站特许的对外接口,可以把我们要找的信息用很完整且规律的方式呈现给我们,打印出来的图片网址如下图:

一模一样的关键词,一摸一样的搜寻引擎,在没有 API 支持下找出来的东西就会东缺西漏的令人不舒服... 并且判断是也更为复杂才能够达到预期的目的。
重新细究代码
如果我们仔细观察输入关键词后的 URL 会发现原本空格隔开的部分都用上了 “+” 替代,因此最一开始就要对人类的输入关键词做预处理,把空格全部改成 “+” 的形式,接下来把改好的词对应放入 URL 中,方法就是用 {} 作为插入位置的标记,使用 XXX.format(name1, name2, ...) 一一插入顺序位置。
重新组装完毕的 URL 就可以被放到加好头档的 urllib 模块功能函数 urlopen() 或是 build_opener().open() 中开始爬虫,回传 data 物件即为一大大大串的 binary string,如果是经由 API 网址的结果,得出来的 string 会充满规律,一切我们期望得到的图片网址都乖乖的安放在 <img src='the target link'> 中,只要使用 bs4 里面的 BeautifulSoup 功能,就可以简单迅速的找出所有匹配结果,并回传成一个 list 格式给这个函数。
但是如果没有 API 就麻烦了,首先得自己经由浏览器解析 HTML 的编码,但事后我们会发现浏览器显示的编码和 urllib 抓取下来的编码尚有些出入,我们需要的图片网址都存在,但是归属存放的标签名称则不同,我这边使用的方法是把抓取下来的 data 转换成字符串,用 split() 切成片段重新组成 list,并用 re.complle 正则表达式去匹配我要的网址格式,最后汇集成为一个完整的 list。
最后储存图片阶段,我们可以用 os.path.join(a, b) 把两个结果合并在一起成为一个 “路径该有的样子” 而不需要我们自己手动去添加 “/” 这类的东西。检查该路径中是否已经有存在同一个文件夹,如果没有的话则用 mkdir 新创一个。并且我们下载如此之多的图片,就要依照下载顺序编号命名,enumerate 作为回圈的话可以输出每一个循环的回合数作为第一个值 (如代码),使用 urllib.request.urlretrieve() 来下载该图片,并放到创建好的资料夹和命名规则。
最后的最后,if __name == "__main__": 这段的解释是让 python 程序可以顺利的执行当前文件下被呼叫的 functions,把那些在不同模块里面(被 import 引用进来的)同名的 functions 在执行的时候屏蔽掉,更多关于 if __name == "__main__": 的详细解释可以参考 [点击1],[点击2]。
















