转载:SSD: Single Shot MultiBox Detector 检测单张图片_ssd单张图片检测-程序员宅基地

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Jesse_Mx/article/details/52965281
                                        <div class="markdown_views">
            <h2 id="前言"><a name="t0"></a><font color="#0099FF">前言</font></h2> 

博主也算是刚开始研究SSD项目,之前写了一篇SSD:Single Shot MultiBox Detector的安装配置和运行,这次是简单介绍下如何用SSD检测单张图片,其实过程也比较简单,下面正式开始。

准备工作

当然,首先你要把SSD按照教程编译好,设置好python环境变量(相当重要),然后重启计算机(建议),开始本次工作。SSD项目检测单张图片有C++程序和ipython程序,这里建议用ipython,主要是方便简单(最近新增了C++程序使用说明)。该工具路径为/home/mx/caffe/example/ssd_detect.ipynb,使用jupyter notebook工具操作。SSD项目常在更新,如果有模型不匹配的问题(报错信息为:shape mismatch. Source param shape is 12 512 3 3 (55296); target param shape is 16 512 3 3 (73728)),请去github下载最新的文件,包括代码和模型

安装 jupyter notebook

这里用pip安装该工具,安装pip的过的可以跳过下面一段:
下载安装包pip压缩包解压之后,发现里面有个setup.py文件,终端运行:

$ sudo python setup.py install
  
  
   
  • 1

这样,pip就安装上了。
下面用pip安装jupyter notebook

#这里临时使用了清华大学的源,使用前后是蜗牛和火箭的速度对比
$ sudo pip install jupyter -i https://pypi.tuna.tsinghua.edu.cn/simple 
  
  
   
  • 1
  • 2

安装成功后,运行notebook

$ jupyter notebook
  
  
   
  • 1

程序会在浏览器中打开notebook, 点击右上角的New-python2, 就可以新建一个网页一样的文件,扩展名为ipynb。在这个网页上,我们就可以像在命令行下面一样运行python代码了。输入代码后,按shift+enter运行,更多的快捷键,可点击上方的help-Keyboard shortcuts查看,或者先按esc退出编辑状态,再按h键查看。

这里写图片描述

下载SSD模型

该工具使用的模型是VGG_VOC0712_SSD_300x300_iter_120000.caffemodel(以前是60000,作者更新了),为了第一次就成功,我们就用它了,这是下载地址 ,下载完后解压,把里面的VGGNet文件夹移动到/home/mx/caffe/models/之下。当然,你掌握这个程序后,完全可以修改路径,检测其他模型的效果。

顺便说下,部分人下载运行上述SSD模型会报错,有些错误很难排查,可以使用我正在使用的SSD300模型,暂时没有问题(对应的是最新的SSD代码):https://pan.baidu.com/s/1eSECLEU

运行程序检测单张图片

$ cd /home/mx/caffe/examples # 在该目录下打开jupyter notebook
$ jupyter notebook
  
  
   
  • 1
  • 2

在jupyter notebook打开的网页中找到ssd_detect.ipynb,打开后发现是这样:

这里写图片描述

完整的程序我就不放出来了,你打开都和我一样,然后检查下面4个路径是否正确:

labelmap_file = 'data/VOC0712/labelmap_voc.prototxt'
model_def = 'models/VGGNet/VOC0712/SSD_300x300/deploy.prototxt'
model_weights = 'models/VGGNet/VOC0712/SSD_300x300/VGG_VOC0712_SSD_300x300_iter_120000.caffemodel'
image = caffe.io.load_image('examples/images/cat.jpg')
  
  
   
  • 1
  • 2
  • 3
  • 4

如果检查无误,就可以开始从头shift+enter运行了,一般会正常运行,也可能会出错,比如我就遇到如下错误:

这里写图片描述

我的办法是,把caffe路径换成绝对路径:

把 caffe_root = ‘../’ 换成 caffe_root = ‘/home/mx/caffe/’ ,理论上不会再出错了,然后在诸如labelmp的路径前面添加caffe_root构成完整的绝对路径,比如:labelmap_file = caffe_root+’data/VOC0712/labelmap_voc.prototxt’

还有一种模型错误也很常见,NameError:name ‘net’ is not defined

在caffe加载正常的情况下出现这种错误,很有可能是deploy.prototxt文件的问题,如果deploy.prototxt最后一层中能查找到save_output_param超参数,删除后能解决问题(后文有详细说明),如果不是,那还要继续排查。

fish-bike.jpg的检测结果如下:

这里写图片描述

换一张复杂一点的图片image = caffe.io.load_image(‘examples/images/my-pic.jpg’) ,检测结果如下:

这里写图片描述

保存运行Python文件

看来效果也是不错的,但是我觉得如果不是去调试代码,每次都打开jupyter notebook运行程序太麻烦,也不方便保存图片之类的操作。这里我的做法是把程序另存为py文件(使用jupyter notebook打开ipynb文件,然后点选另存为),稍作修改,再单独运行这个py文件即可。改动的地方貌似只有一处,就是把get_ipython().magic(u'matplotlib inline')这句话给注释掉,因为脱离了jupyter notebook的环境,用不上了。然后python ssd_detect.py,代码正常,没有报错,但是无法弹出窗口显示最终的带框图片,上网查询一番,原因是是默认的matplotlib的backend(后端)渲染有问题。那么先查看目前的后端情况:

Python 2.7.12 (default, Jul  1 2016, 15:12:24) 
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import matplotlib
>>> matplotlib.get_backend()
u'Agg'
  
  
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

目前是Agg,但为了正确将图像显示在屏幕上,需要设置为TkAgg,解决方法是安装几个库文件:

$ sudo apt-get install tcl-dev tk-dev python-tk python3-tk
  
  
   
  • 1

重启电脑,再次查看,这里应该是变成了TkAgg,如果没有变化,那还可以sudo pip uninstall matplotlib 先卸载,然后pip install matplotlib 安装回去,重启电脑,这样就可以确保后端设置变成TkAgg。如此设置后再运行py程序,就完全正常了,下图为博主的运行截图。

这里写图片描述

其实这种程序也是学习pycaffe的好帮手,推荐博文:Caffe Python 接口学习笔记,如果不懂某个函数,记得善用help,比如:

>>>import caffe
>>>help(caffe.io)

Help on module caffe.io in caffe:
NAME
    caffe.io
FILE
    /home/mx/caffe/python/caffe/io.py
CLASSES
    Transformer    
    class Transformer
     |  Transform input for feeding into a Net.
     |  
     |  Note: this is mostly for illustrative purposes and it is likely better
     |  to define your own input preprocessing routine for your needs.
     |  
     |  Parameters
     |  ----------
     |  net : a Net for which the input should be prepared
     |  
     |  Methods defined here:
     |  
  
  
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

附:
ssd_detect.ipynb 可运行版
ssd_detect.py

—————————————–分割线————————————-

关于ssd_detect.cpp

好像有部分同学比较关心ssd的C++检测图片程序,也就是ssd_detect.cpp的用法。我们知道,C++程序要经过编译,生成可执行程序才能进行使用(把它作为一个类来调用则是另外一回事了),这个cpp理论上也是可以编译的,有评论说Eclipse中实现了编译,前提是你要会配置那些依赖项,我尝试用“g++ -o ssd_detect ssd_detect.cpp”来进行编译,发现一直报错,主要是找不到需要的include项,很自然的想到添加CPLUS_INCLUDE_PATH环境变量来解决,可是后来又遇到google proto等等的问题,凭我这种三流水平只能投降了,暂时宣告手动编译cpp失败。

其实呢,这个cpp最好是通过make命令(Makefile文件指定包含目录和依赖项等)编译。所以,我们在配置caffe阶段make all的时候,已经从ssd_detect.cpp生成了可执行的二进制文件(留意make all命令的终端显示就可知道),也就是ssd的C++接口程序,路径就在caffe/build/examples/ssd/ssd_detect.bin。那好,我们先看一下它的用法。

ps:最新博客已经实现了eclipse的SSD配置,可以移步:Ubuntu 16.04使用Eclipse运行SSD-Caffe的cpp代码

终端输入:

$ cd caffe
$ build/examples/ssd/ssd_detect.bin
#使用方法说明
ssd_detect.bin: Do detection using SSD mode.
Usage:
    ssd_detect [FLAGS] model_file weights_file list_file


  Flags from examples/ssd/ssd_detect.cpp:
    -confidence_threshold (Only store detections with score higher than the
      threshold.) type: double default: 0.01
    -file_type (The file type in the list_file. Currently support image and
      video.) type: string default: "image"
    -mean_file (The mean file used to subtract from the input image.)
      type: string default: ""
    -mean_value (If specified, can be one value or can be same as image
      channels - would subtract from the corresponding channel). Separated by
      ','.Either mean_file or mean_value should be provided, not both.)
      type: string default: "104,117,123"
    -out_file (If provided, store the detection results in the out_file.)
      type: string default: ""
  
  
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

可以看到,该程序需要三个必选参数以及一些可选参数,必选参数首先是model_file,也就是检测模型描述文件;然后是weights_file,网络权值文件;list_file,待检测文件,格式为txt,里面列出检测图片/视频的路径。可选参数包括阈值、文件格式、均值文件、图片均值、输出文件这些,都有解释,一看就懂。

运行一个命令试试:

$ cd caffe
$ build/examples/ssd/ssd_detect.bin models/VGGNet/VOC0712/SSD_300x300/deploy.prototxt models/VGGNet/VOC0712/SSD_300x300/VGG_VOC0712_SSD_300x300_iter_120000.caffemodel examples/images/test.txt 
  
  
   
  • 1
  • 2

其中test.txt内容为“examples/images/cat.jpg”,是待检测图片的路径,可以写多行。

呵呵,又报错了:“ImportError: libcaffe.so.1.0.0-rc3: cannot open shared object file: No such file or directory”,还好这个错误在本人知识范围内,也就是静态链接库的问题,so easy。

$ cd /etc/ld.so.conf.d
$ sudo vi caffe.conf 
# conf文件加入 /home/mx/caffe/.build_release/lib,保存退出
sudo ldconfig
  
  
   
  • 1
  • 2
  • 3
  • 4

也有可能会出现这种错误:terminate called after throwing an instance of ‘boost::filesystem::filesystem_error’ what(): boost::filesystem::create_directories: Permission denied: “/home-2/wliu/data/VOCdevkit/results/VOC2007/SSD_300x300”。原因是作者提供的最新SSD300模型中deploy.prototxt里面有些东西(代码如下)没有删干净,找到最后一层,直接把超参数save_output_param整个删掉(也可以替换为个人路径)。

save_output_param {
      output_directory: "/home-2/wliu/data/VOCdevkit/results/VOC2007/SSD_300x300/Main" output_name_prefix: "comp4_det_test_" output_format: "VOC" label_map_file: "data/VOC0712/labelmap_voc.prototxt" name_size_file: "data/VOC0712/test_name_size.txt" num_test_image: 4952 } #deploy.prototxt的错误代码,里面是原作者个人路径,可以直接删除
  
  
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

然后重新运行检测命令,这次有结果了:examples/images/cat.jpg 8 0.999853 163 38 350 358

这个C++程序目前只能得到这样的描述结果,想要可视化的结果要么写一个程序读取里面的文本信息,然后用opencv画框;也可以修改源cpp程序重新编译,这个还没尝试,等有空了研究。

复杂一些的例子,检测视频(得到的结果也是每一帧的文本描述),改变阈值并保存检测结果:

$ build/examples/ssd/ssd_detect.bin models/VGGNet/VOC0712/SSD_300x300/deploy.prototxt models/VGGNet/VOC0712/SSD_300x300/VGG_VOC0712_SSD_300x300_iter_120000.caffemodel examples/videos/test.txt --file_type video --out_file output.txt --confidence_threshold 0.4 #检测视频,阈值为0.4并保存结果
  
  
   
  • 1

ssd_detect.cpp检测结果的可视化

之前博主说过,只用ssd_detect.bin检测图片,只能得到一些文本描述结果,大家想要的其实是可视化的带框图片。原本还想自己写一个小程序实现,结果是我想多了,作者已经在新一版的SSD中增加了这一功能,具体而言,就是examples/ssd/plot_detections.py文件。下面来说说怎么用。

首先想到这个py文件多半是读取一些参数(examples/images/cat.jpg 8 0.999853 163 38 350 358这种)才能画框,那么打开这个py文件,找一下接口部分:

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
            description = "Plot the detection results output by ssd_detect.")
    parser.add_argument("resultfile",
            help = "A file which contains all the detection results.")
    parser.add_argument("imgdir",
            help = "A directory which contains the images.")
    parser.add_argument("--labelmap-file", default="",
            help = "A file which contains the LabelMap.")
    parser.add_argument("--visualize-threshold", default=0.01, type=float,
            help = "Display detections with score higher than the threshold.")
    parser.add_argument("--save-dir", default="",
            help = "A directory which saves the image with detection results.")
    parser.add_argument("--display-classes", default=None,
            help = "If provided, only display specified class. Separate by ','")
  
  
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

果不其然,包含2个必选参数和4个可选参数。必选参数是检测结果文件txt、原始图片文件夹;可选参数有labelmap.prototxt、筛选阈值、保存路径、特定的类别(比如只显示汽车的检测结果)。

先前已经用ssd_detect.bin得到了自带图片的检测结果,存为result.txt:

examples/images/cat.jpg 8 0.999429 169 26 347 356
examples/images/cropped_panda.jpg 12 0.975958 0 1 95 97
examples/images/fish-bike.jpg 2 0.717551 52 81 448 307
examples/images/fish-bike.jpg 15 0.99994 204 3 344 170
  
  
   
  • 1
  • 2
  • 3
  • 4

下面开工,用一下这个py文件:

$ python examples/ssd/plot_detections.py examples/images/result.txt examples/images --labelmap-file data/VOC0712/labelmap_voc.prototxt --save-dir examples/
  
  
   
  • 1

立马报错:

examples/images/examples/images/cat.jpg does not exist
examples/images/examples/images/cropped_panda.jpg does not exist
examples/images/examples/images/fish-bike.jpg does not exist

看来图片路径没对,txt中已经有了图片路径,造成路径重复,这个参数不能这么写,但是不写肯定不行。动下脑筋,变成绝对路径不就行了吗。

$ python examples/ssd/plot_detections.py examples/images/result.txt /home/mx/caffe --labelmap-file data/VOC0712/labelmap_voc.prototxt --save-dir examples/
  
  
   
  • 1

现在好了,在examples文件夹下找到了三张图片,已经画好框,大功告成。
这里写图片描述
这里写图片描述
这里写图片描述



版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/anqian123321/article/details/82023965

智能推荐

c# 调用c++ lib静态库_c#调用lib-程序员宅基地

文章浏览阅读2w次,点赞7次,收藏51次。四个步骤1.创建C++ Win32项目动态库dll 2.在Win32项目动态库中添加 外部依赖项 lib头文件和lib库3.导出C接口4.c#调用c++动态库开始你的表演...①创建一个空白的解决方案,在解决方案中添加 Visual C++ , Win32 项目空白解决方案的创建:添加Visual C++ , Win32 项目这......_c#调用lib

deepin/ubuntu安装苹方字体-程序员宅基地

文章浏览阅读4.6k次。苹方字体是苹果系统上的黑体,挺好看的。注重颜值的网站都会使用,例如知乎:font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, PingFang SC, Microsoft YaHei, Source Han Sans SC, Noto Sans CJK SC, W..._ubuntu pingfang

html表单常见操作汇总_html表单的处理程序有那些-程序员宅基地

文章浏览阅读159次。表单表单概述表单标签表单域按钮控件demo表单标签表单标签基本语法结构<form action="处理数据程序的url地址“ method=”get|post“ name="表单名称”></form><!--action,当提交表单时,向何处发送表单中的数据,地址可以是相对地址也可以是绝对地址--><!--method将表单中的数据传送给服务器处理,get方式直接显示在url地址中,数据可以被缓存,且长度有限制;而post方式数据隐藏传输,_html表单的处理程序有那些

PHP设置谷歌验证器(Google Authenticator)实现操作二步验证_php otp 验证器-程序员宅基地

文章浏览阅读1.2k次。使用说明:开启Google的登陆二步验证(即Google Authenticator服务)后用户登陆时需要输入额外由手机客户端生成的一次性密码。实现Google Authenticator功能需要服务器端和客户端的支持。服务器端负责密钥的生成、验证一次性密码是否正确。客户端记录密钥后生成一次性密码。下载谷歌验证类库文件放到项目合适位置(我这边放在项目Vender下面)https://github.com/PHPGangsta/GoogleAuthenticatorPHP代码示例://引入谷_php otp 验证器

【Python】matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距-程序员宅基地

文章浏览阅读4.3k次,点赞5次,收藏11次。matplotlib.plot画图横坐标混乱及间隔处理_matplotlib更改横轴间距

docker — 容器存储_docker 保存容器-程序员宅基地

文章浏览阅读2.2k次。①Storage driver 处理各镜像层及容器层的处理细节,实现了多层数据的堆叠,为用户 提供了多层数据合并后的统一视图②所有 Storage driver 都使用可堆叠图像层和写时复制(CoW)策略③docker info 命令可查看当系统上的 storage driver主要用于测试目的,不建议用于生成环境。_docker 保存容器

随便推点

网络拓扑结构_网络拓扑csdn-程序员宅基地

文章浏览阅读834次,点赞27次,收藏13次。网络拓扑结构是指计算机网络中各组件(如计算机、服务器、打印机、路由器、交换机等设备)及其连接线路在物理布局或逻辑构型上的排列形式。这种布局不仅描述了设备间的实际物理连接方式,也决定了数据在网络中流动的路径和方式。不同的网络拓扑结构影响着网络的性能、可靠性、可扩展性及管理维护的难易程度。_网络拓扑csdn

JS重写Date函数,兼容IOS系统_date.prototype 将所有 ios-程序员宅基地

文章浏览阅读1.8k次,点赞5次,收藏8次。IOS系统Date的坑要创建一个指定时间的new Date对象时,通常的做法是:new Date("2020-09-21 11:11:00")这行代码在 PC 端和安卓端都是正常的,而在 iOS 端则会提示 Invalid Date 无效日期。在IOS年月日中间的横岗许换成斜杠,也就是new Date("2020/09/21 11:11:00")通常为了兼容IOS的这个坑,需要做一些额外的特殊处理,笔者在开发的时候经常会忘了兼容IOS系统。所以就想试着重写Date函数,一劳永逸,避免每次ne_date.prototype 将所有 ios

如何将EXCEL表导入plsql数据库中-程序员宅基地

文章浏览阅读5.3k次。方法一:用PLSQL Developer工具。 1 在PLSQL Developer的sql window里输入select * from test for update; 2 按F8执行 3 打开锁, 再按一下加号. 鼠标点到第一列的列头,使全列成选中状态,然后粘贴,最后commit提交即可。(前提..._excel导入pl/sql

Git常用命令速查手册-程序员宅基地

文章浏览阅读83次。Git常用命令速查手册1、初始化仓库git init2、将文件添加到仓库git add 文件名 # 将工作区的某个文件添加到暂存区 git add -u # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,不处理untracked的文件git add -A # 添加所有被tracked文件中被修改或删除的文件信息到暂存区,包括untracked的文件...

分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120-程序员宅基地

文章浏览阅读202次。分享119个ASP.NET源码总有一个是你想要的_千博二手车源码v2023 build 1120

【C++缺省函数】 空类默认产生的6个类成员函数_空类默认产生哪些类成员函数-程序员宅基地

文章浏览阅读1.8k次。版权声明:转载请注明出处 http://blog.csdn.net/irean_lau。目录(?)[+]1、缺省构造函数。2、缺省拷贝构造函数。3、 缺省析构函数。4、缺省赋值运算符。5、缺省取址运算符。6、 缺省取址运算符 const。[cpp] view plain copy_空类默认产生哪些类成员函数

推荐文章

热门文章

相关标签