何为 YOLO(You Only Look Once)

YOLO [点击] 充满青春暗示的另一面,更是一个强大物体检测算法的简称,其算法结合了速度与准确度,近期更推出了第三版的 model 供大家参考,大幅度提升了前一版的性能。作者为一位资深 computer scientist: Joseph Chet Redmon 精通数据科学,编程等工作,与另外四名伙伴一同开发了此模型。

与以往的重复定位不同图片区域,并多次加权算出最高的得分区域来衡量该物体的属性与位置不同,YOLO 采用了一次性的神经网络层,直接平行分析图片中每个区域的各种可能,并在可能性最大的区域画出一个方框后标记方框内的物体对应的属性。这样的流程大幅提升准确度和计算速度,击败诸多先前模型的 performance。更详细的描述可以参考此篇文章 [点击]。

我作为一个计算机小白出身的光学工程师,学习之路走到今天能用上大神推行出来的物体检测算法来应用到自己的电脑上,已经是无比激动的一件事情了。从 Python 代码的编写学习,到模块包应用如:os, re, bs4, math, urllib, cv2, numpy, moviepy, ... 等等,再跳到现在的综合考验环节,做出自己设定结果的瞬间,只想感谢强大的万维网提供如此之完备的资源能够让一个人独立完成所有工作。一方面为了加深自己对此领域的记忆,一方面也希望自己淌过的坑可以说出来和大家分享,让同为这方面的爱好者有个前车之鉴,但是本人资历尚浅,要是描述中有何不妥也衷心感谢大神们的回馈!

实时物体检测的主要三环节

  1. 搜集数据
    面对成千上万的物体种类与名称,必须预先搜集我们期望机器了解的种类的图像数据,通常需要上千张类似的图片作为资料库,面对庞大的量我们将会选择使用简单爬虫的方法,利用常见的搜寻引擎如 Google 或是 Baidu 作为主要手段。
  2. 标记数据
    搜集好数据后,接下来的步骤就是手把手的教导机器 “什么是什么” 环节。面对每张涵盖了相关信息内容的图片,我们将基于这些图片生成一个 xml 文档来记录相关物体的坐标信息,并以此 xml 文档与对应图片作为输入要件,进入到下一个步骤。
  3. 训练模型
    下载好相关的 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:

# 一个用来调用网路资源的包,包含解析网址,设定头档
import urllib.request as urst
# 全名为 Regular Expression 正则表达式,用来 “制定规则” 的匹配机制
import re
# 一个可以让我们自由方便操纵系统文件与路径的包
import os
# 一个全世界电脑通用的数据格式包,可以方便处理 json 文档里面的信息
import json
# 一个运算超级快速的数字相关的科学工具,用来处理数字提升效率
import numpy as np
# 一个用来对付 Tag 和其里面内容之资料形态的包,可以很方便帮我们把我们需要的信息剥离出来
from bs4 import BeautifulSoup as bs# 建立一个头档,让对方的 server 以为是我们使用浏览器的方式登入他们网站,避免不必要的阻拦
opener = urst.build_opener()
hd = ('User-Agent', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:55.0) Gecko/20100101 Firefox/55.0')
opener.addheaders = [hd]# 网址如果使用该公司提供的 API,则代入浏览器里面的 URL 位置找到的将不再是网页,而是一个 json 文件
googleSearch = 'https://www.google.com/search?ei=1m7NWePfFYaGmQG51q7IBg&hl=en&q={}\&tbm=isch&ved=0ahUKEwjjovnD7sjWAhUGQyYKHTmrC2kQuT0I7gEoAQ&start={}\&yv=2&vet=10ahUKEwjjovnD7sjWAhUGQyYKHTmrC2kQuT0I7gEoAQ.1m7NWePfFYaGmQG51q7IBg\.i&ijn=1&asearch=ichunk&async=_id:rg_s,_pms:s'
baiduSearch = 'http://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word={}'# 定义一个函数,能够让我们输入关键词之后,借由 google 的搜寻回传一组全是图片网址组成的 list
def google_get_links(keywords):# 人类的语言使用空格分离,但是在 URL 的规则中,空格要使用 “+” 替代keywords = keywords.replace(' ', '+')# 把处理好的重组关键词放入到对应的网址位置中,0表示低0页(即可)google_url = googleSearch.format(keywords, 0)# 使用 urllib 包打开重组好的网址,并且 “读” 里面的内容后,赋值于 data 这个自创的 objectdata = opener.open(google_url).read()# 把被赋值的 data object 转换成 json 格式的 list 信息page = json.loads(data)# 使用 bs4 的方法过滤 Tag 内容前的预处理,把 object 转换成 bs4 对应的属性soup = bs(page[1][1], 'lxml', from_encoding='utf-8')# 找出所有名为 ”img” 的标签img_tags = soup.findAll('img')# 找出 img 标签中国呢备注了 ‘src' 里面的内容,也就是我们要的网址links = [target.get('src') for target in img_tags]# 最后遍历到一个 list 里面会传给该函数return links# 定义一个函数,能够让我们输入关键词之后,借由 baidu 的搜寻回传一组全是图片网址组成的 list
def baidu_get_links(keywords):keywords = keywords.replace(' ', '+')baidu_url = baiduSearch.format(keywords)data = opener.open(baidu_url).read()soup = bs(data, 'lxml', from_encoding='utf-8')img_tags = soup.findAll('script', {'type': 'text/javascript'})# 定义一个空的 list 用来承载在回圈中被不断添加的内容links = []# 由于这边没有使用 API,所以找出来的东西会很杂乱,需要自行解析,自行找规则for chaos in img_tags:chaos_str = chaos.string# 有的内容是 None,在判断式那边会报错,因此直接加上 try 来把这个问题避开,如果报错了,就 continue 即可try:if 'ObjURL' in chaos_str:# 发现了‘ObjURL’ 后面的网址就是我们要的网址,因此用这个词把字符串分段组成新的 listSplit = chaos_str.split('objURL":"')# 使用正则匹配后面我们期望看到的网址样貌,记得使用的是 ”懒惰模式“target_format = re.compile('^(http)s?.*?[^"]?.*?(jpg|png|jpeg|gif)')for chaos_split in Split:                     # 同样为了达到避免报错的目的,而设置的 try / excepttry:# 把匹配成功的内容放到那个空的 list 里面i = target_format.match(chaos_split).group()links.append(i)except:continueexcept:continuereturn links# 定义一个函数用来把上面形成 list 的图片网址集合下载下来,并根据其搜寻名称放置到我们喜欢的文件夹路径中
def save_images(links_list, keywords):# 由于在使用电脑呼叫文件的时候,不希望看到空格,因此这边使用 "_" 替代folderName = keywords.replace(' ', '_')# 使用 join 好处是只要输入两个谁前谁后要排起来的路径名即可,不用中间还自己加 "/" 之类的东西directory = os.path.join(input('Enter the path to store the images: '), folderName)# 如果那个路径里面没有这个文件夹,那就创造一个,有的话就莫不作为if not os.path.isdir(directory):os.mkdir(directory)for sequence, link in enumerate(links_list):# 使用该图片网址在 list 中的排序来命名,并且重新生成一个最终的下载状态(包含档名)savepath = os.path.join(directory, '{:06}.png'.format(sequence))# 如果图片文件夹里面有一些隐藏文件,会导致下载失败,那就用 try 避开,让程序继续运行下去try:# 用这函数下载图片网址,并且把下载下来的东西放到指定的路径里面urst.urlretrieve(link, savepath)except:continue# 如果呼叫的这些函数名字都是写在这个文档的函数,并非 import 进来的话,则运行;否则忽略
if __name__ == '__main__':keyword = 'audi'links_from_google = google_get_links(keyword)# links_from_baidu = baidu_get_links(keyword)save_images(links_from_google, keyword)

设计代码的时候,python 环境中的我们同样倾向于模块化的功能编写,这样不仅写出来的代码逻辑性强,如果模块的名字取得好,那写出来的代码就可以说是超级易懂的了。整体代码步骤如下:

  1. 引入需要用到的模块
  2. 为了防止网站反爬虫机制,做一个头档(hd)去伪装自己像是个浏览器
  3. 使用 “图片” 搜寻引擎的 API 作为网址(如果直接去图片搜寻的网页把其 URL 拷贝也是可以,只是效率低下,原因稍后说明)
  4. 定义第一个功能函数 google_get_links(keyword) ,拿一个关键词作为输入,以 google 搜寻作为手段输出一个装满相关图片网址的 list,同样的逻辑适用于函数 baidu_get_links(keyword)
  5. 定义第三个功能函数 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]。

点击此处通往下集  [ YOLO... (中)... ]

YOLO3 + Python3.6 深度学习篇(上)- Transfer Learning 迁移学习相关推荐

  1. 【深度学习】一文看懂 (Transfer Learning)迁移学习(pytorch实现)

    前言 你会发现聪明人都喜欢"偷懒", 因为这样的偷懒能帮我们节省大量的时间, 提高效率. 还有一种偷懒是 "站在巨人的肩膀上". 不仅能看得更远, 还能看到更多 ...

  2. Transfer Learning 迁移学习的相关知识

    通俗讲,机器学习领域,如果从0开始学习知识,成本高,速度慢. -------- 个人技术公众号:解决方案工程师 欢迎同领域的朋友关注.相互交流. -------- 1:什么是迁移学习? 通俗讲,机器学 ...

  3. 【翻译】 A survey of transfer learning迁移学习综述

    原文https://www.cse.ust.hk/~qyang/Docs/2009/tkde_transfer_learning.pdf 该文主要对A Survey on Transfer Learn ...

  4. 【详解】Transfer learning迁移学习 附代码

    迁移学习的训练策略: 1.先冻结卷积层只训练全链接层,这一步需要把结果最好的那个模型保存起来. 2.加载上一步保存的那个最优模型,在这个模型的基础上,再以更小的学习率训练所有层,更新网络的所有权重参数 ...

  5. 机器学习-44-Transfer Learning(迁移学习)

    文章目录 Transfer Learning why?(为什么要迁移学习?) Overview(概述) Target Data labelled & Source Data labelled ...

  6. 迁移学习简介(transfer learning)

    迁移学习简介(transfer learning) https://blog.csdn.net/qq_33414271/article/details/78756366 一.什么是迁移学习? 迁移学习 ...

  7. 讨论丨深度学习已经成为过去?迁移学习才是真正的未来?

    大牛吴恩达曾经说过:做AI研究就像造宇宙飞船,除了充足的燃料之外,强劲的引擎也是必不可少的.假如燃料不足,则飞船就无法进入预定轨道.而引擎不够强劲,飞船甚至不能升空.类比于AI,深度学习模型就好像引擎 ...

  8. 数据不够怎么训练深度学习模型?不妨试试迁移学习 ——重用神经网络的结构2...

    数据不够怎么训练深度学习模型?不妨试试迁移学习 本质就是这个图!pretrained model就是你截取的部分神经网络模型(迁移学习),而nanonet就是你自己加入的网络层. 随着深度学习技术在机 ...

  9. 深度学习笔记(18) 迁移学习

    深度学习笔记(18) 迁移学习 1. 迁移学习理念 2. 图像识别的迁移学习 3. 语音识别的迁移学习 4. 使用迁移学习的场合 1. 迁移学习理念 深度学习中最强大的理念之一就是: 神经网络可以从一 ...

最新文章

  1. Nginx 一个牛X的功能,流量拷贝!
  2. 《Java并发编程入门与高并发面试》or 《Java并发编程与高并发解决方案》笔记
  3. tensorflow2.X安装及使用
  4. 【Android工具】高端DLNA音乐播放器Hi-Fi Cast 来自play
  5. SAP Commerce Cloud Spartacus UI 的 ActionClass 数据结构设计
  6. JavaScript基础介绍
  7. poj 1469(二分图最大匹配)
  8. SharePoint 2013版本功能对比介绍
  9. Nuget包管理工具(程序包控制台执行语句)
  10. CSUOJ 1111 三家人
  11. Arturia Pigments for Mac - 虚拟振荡合成器
  12. tomcat 8优化配置
  13. gc java 单核_JAVA应用性能监控之JVM层GC调优
  14. Codeforces-710E Generate a String
  15. 遗传算法求解tsp问题 C语言,遗传算法解决TSP问题(C++)
  16. PG数据库创建视图并授权给新用户
  17. C语言之结构体 共用体 枚举 typedef
  18. kali下钓鱼网站的制作
  19. php获取ip归属地
  20. wps office 2013 利用wps文字制作一张漂亮的座位表

热门文章

  1. 数据仓库和传统数据库的关系
  2. Android平板电脑应用开发的技巧和注意点
  3. 串口调试日志打印颜色输出
  4. 一元一次方程的解析解(基本字符串处理)
  5. PMP二模知识点集锦
  6. python基础--循环--模拟骰子
  7. python编程有什么用-学了Python编程之后,同是新手的他们做了什么?
  8. 人工学院2卡顿_人工学院2为什么那么卡 | 手游网游页游攻略大全
  9. CaesarCipher凯撒密码
  10. 如何防治游戏内的“黑产”拉人?