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)

     

     

     

  • 相关阅读:
    173. Binary Search Tree Iterator
    199. Binary Tree Right Side View
    230. Kth Smallest Element in a BST
    236. Lowest Common Ancestor of a Binary Tree
    337. House Robber III
    449. Serialize and Deserialize BST
    508. Most Frequent Subtree Sum
    513. Find Bottom Left Tree Value
    129. Sum Root to Leaf Numbers
    652. Find Duplicate Subtrees
  • 原文地址:https://www.cnblogs.com/zealousness/p/8757704.html
Copyright © 2011-2022 走看看