zoukankan      html  css  js  c++  java
  • caffe web demo运行+源码分析

    caffe web demo学习

    1、运行

    安装好caffe后,进入/opt/caffe/examples/web_demo/的caffe web demo项目目录,查看一下app.py文件,这是一个flask编写的网站

    查看readme.md了解该项目,查看requirements.txt了解所需的python包

    然后运行该项目:python app.py,发现报错

    class_labels_file is missing

    网上说还需要下载一些data,运行下面两条命令:

    确保已经下载了 Reference CaffeNet Model 和 the ImageNet Auxiliary Data:

    python opt/caffe/scripts/download_model_binary.py models/bvlc_reference_caffenet

    opt/caffe/data/ilsvrc12/get_ilsvrc_aux.sh

    然后再运行该项目:python app.py

     

    127.0.0.1:5000查看

     

     

    2、app.py源码分析

    这个web demo使用了在ilsvrc2012比赛的数据集上训练得到的模型。

    模型已经预先训练好,并给出了模型的网络结构文件deploy.prototxt,训练好的模型文件bvlc_reference_caffenet.caffemodel,训练数据的均值文件ilsvrc_2012_mean.npy(需要它是因为需要对测试数据去均值),标签序号与标签内容的对应文件synset_words.txt,与原始数据集结构有关的imagenet.bet.pickle

    其中网络结构文件、训练好的模型文件、均值文件会被输入到caffe.Classifier里用来构造分类器,标签序号与标签内容文件用来在网页上给显示结果。

     

    1)index函数

     

     

    2)classify_url函数

    读取url,urllib.urlopen().read()打开url并读取出二进制字节流(python3中为urllib.request.urlopen().read()),caffe.io.load_image()转换为caffe能接受的格式,输出日志,调用classify_image识别图片,将识别结果和imageurl渲染回html显示给用户

     

    3)classify_upload函数

    获取上传的图片,在文件名前插入时间以区分不同文件,将文件保存到服务器,输出日志,调用classify_image识别图片,将识别结果和图片(以base64编码的形式)渲染回html显示给用户

     

     

     

    4)embed_image_html函数

    3)服务,读取文件返回base64编码

     

     

    5)allowed_file函数

    检查文件后缀名是否在可接受的类型中(这个函数在app.py中并没有被调用,不知道为什么)

     

     

    6)ImagenetClassifier内部类

    定义了5个默认参数:模型的网络结构文件deploy.prototxt,训练好的模型文件bvlc_reference_caffenet.caffemodel,训练数据的均值文件ilsvrc_2012_mean.npy(需要它是因为需要对测试数据去均值),标签序号与标签内容的对应文件synset_words.txt,与原始数据集结构有关的imagenet.bet.pickle

    for循环验证了这些文件存不存在,不存在的话报错(安装过程中的报错就是这里抛出的)

    定义了2个默认参数,image_dim表示???,raw_scale表示???

     

    初始化指定识别使用cpu还是gpu

    初始化分类器:caffe.Classifier,接收上面定义的模型的网络结构文件deploy.prototxt,训练好的模型文件bvlc_reference_caffenet.caffemodel,训练数据的均值文件ilsvrc_2012_mean.npy(需要它是因为需要对测试数据去均值)三个参数

    。。。。。。。

     

    7)中

    app.clf = ImagenetClassifier(**ImagenetClassifier.default_args)
    app.clf.net.forward()

    两句代码执行完之后,我们实际上就创建并训练好我们的分类器了。

    然后我们调用net.predict函数,将caffe.io.load_image得到的图片传进去,就可以进行识别,并返回一个numpy.ndarray类型的最后一层(输出层)的结果。

    net.predict完之后,识别的中间结果也已经存在app.clf.net中了,只需要调用net.blobs['layer名'].data就可以获取到numpy.ndarray类型的中间结果了。

    predict时的oversample表示过取样,默认为true

    ndarray.shape可以获取ndarray数组的形状,更多源于numpy.ndarray数组的信息见这篇https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.html

    ndarray.flatten表示把ndarray多维数组展开成一维ndarray数组,见这篇https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.ndarray.flatten.html

    ndarray数组前面加负号表示对每个元素取负值

    ndarray.argsort不改变原数组,并返回原数组值从小到大的索引值,示例如下,或见这篇http://blog.csdn.net/maoersong/article/details/21875705

      >>> x = np.array([3, 1, 2])
        >>> np.argsort(x)
        array([1, 2, 0])

     

    个人通过加了如下几行代码看了一下这个模型各层结果的格式:(在使用logging.info的过程中注意,logging.info的输出要通过%s来占位,不同于print可直接输出)

    # add by zss
    # logging.info('classifier.predict.faltten:%s',list(scores))
    # logging.info('classifier.predict:%s',list(self.net.predict([image],oversample=True)))
    logging.info('########################:%s',list(self.net.blobs['fc8'].data[1]))

    如下:

    predict函数返回的最后一层(prob层)的结果格式为1*1000的概率数组(值在0-1之间)

    ‘fc8’层的结果,格式为10*1000的概率数组(值在0-1之间)

    分析:

    prob层和fc8层的结果对应着1000个标签,含义是该图片是该标签的概率。

    fc8层有10个长度1000的数组是因为我们在定义模型(caffe.Classifier())时,对oversample选项采用了默认值true,开启了过取样,相当于将每张图片经过旋转和镜像对称变成了10张相同的图片,所以fc8层有10个结果,然后prob层将这10个结果综合得到了最终结果1*1000的概率数组),关于oversample过取样见这篇http://blog.csdn.net/guoyilin/article/details/42886365

     

    ‘fc7’层的结果,格式为10*4096的foat数组(值可能大于1),形如下图

    分析:

    fc7层的结果对应着输入的那一张图片,经过过取样后的10张图片,各自的4096个特征的值

     

     

     

    7)start_tornado函数

    8)服务,启动flask服务器

    不太明白,为什么要用tornado的函数启动flask服务器?

     

     

    8)start_from_terminal函数

    9)服务,使用optparse定义了一些参数debug,port,gpu,用来控制debug模式是否打开,flask运行的端口,gpu模式还是cpu模式,运行flask的端口号,然后调用7)启动flask服务器

     

    9)命令行启动

    设置log级别,创建用来存储用户上传的图片的临时文件夹,调用8)

     

     

     

  • 相关阅读:
    python(六):反射
    python模块之contexlib
    python(五):元类与抽象基类
    python之hashlib模块
    python(四):面型对象--类的特殊方法
    20145226夏艺华 《Java程序设计》第1周学习总结
    20145226夏艺华 《Java程序设计》第10周学习总结
    20145226夏艺华 《Java程序设计》实验报告四
    20145226夏艺华 《Java程序设计》第9周学习总结
    20145226夏艺华 《Java程序设计》第8周学习总结
  • 原文地址:https://www.cnblogs.com/zealousness/p/8757704.html
Copyright © 2011-2022 走看看