利用Python web框架Django實現py-faster-rcnn demo實例


---作者疆,未經允許,嚴禁轉載,違權必究---

---歡迎指正,需要源碼和文件可站內私信聯系---

-----------點擊此處鏈接至博客園原文-----------

 

功能說明:利用Python web框架Django,將faster-rcnn的demo程序以網頁形式展現出來,簡而言之是基於B-S架構的編程,直觀地以網頁形式展示目標檢測的功能。

運行環境:Window7  cpu  Python2.7  Pycharm5.0  Django1.8x

 

一、功能預覽

首先,啟動服務器,將返回一個網址: http://127.0.0.1:8000/ 即本機地址 (模擬網頁,本機同時是服務器和模擬前端用戶)

然后,我們可以登錄上面給出的地址

 

接着,我們輸入相關內容,點擊ok

等待網頁返回處理后的結果(樓下俺的女朋友)

可以看到此時后台在執行faster rcnn相關代碼

 

如果想復現上述功能,請按本人寫作順序依次進行相關操作。

 

二、Django環境的搭建

參考鏈接:Django自學之路

以本人Windows7系統為例看上述參考鏈接中Django環境搭建2.1.2部分,建議選Django1.8版本,便於后續學習。建議自主學習本網址Django視圖與網址部分,半小時就能理解。大致能對新建Django工程、工程目錄下應有什么文件、以及主要的一些文件如views.py、urls.py的作用有個清晰的理解,這些內容還是靜靜地學習這個網址的講解,后文我也會提及一部分。以下是本人安裝Django的簡要筆記,大略可以參考一下。

 

三、本文Django工程中的文件上傳機制

參考這篇博客,其基於deepin linux 2013、Python 2.7、Django 1.6.2環境實現的,由於本人環境為Window7 Django1.8,因此需要做部分修改,結合上述參考blog做如下操作:

(1)創建項目應用

這部分內容在”一”中所給參考鏈接中講解的非常清楚,本人Django工程地址:E:\deep learning\py-faster-rcnn-master\tools\,首先cmd模式下cd到你想放置的路徑,然后輸入django-admin.py startproject mysite2 即可創建一個名為mysite2的Django工程,接着cd到mysite2的路徑   cd mysite2,在項目下創建一個disk應用   python manage.py startapp disk,這時,可以在相應位置看到新建的Django工程,以及可以看到類似於下面的Django工程目錄結構。

 

打開mysite2/mysite2/settings.py,將disk應用添加進去,如下所示:

# Application definition

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'disk',
)

(2)設計model(數據庫)

打開mysite2/disk/models.py,添加如下內容即可創建兩個字段,username用於存放用戶名、headImg用於存放上傳圖片路徑。

from django.db import models

# Create your models here.
class User(models.Model):
    username = models.CharField(max_length = 30)
    headImg = models.FileField(upload_to = './upload/')
    def __unicode__(self):
        return self.username

后面執行上傳圖片操作時,會將圖片傳至upload文件夾內。

(3)數據庫同步

cmd模式下cd 到Django工程mysite2(第一級的mysite2)下,依次敲入以下命令(由於本人版本不同所以命令與上述參考博客中略有不同),按提示依次輸入python manage.py  syncdb,python manage.py  makemigration,python manage.py  migrate,正常情況下,cmd窗口應該會顯示以下內容:(忽略我這里設置的路徑,我剛開始默認存在c盤的,為了方便工作我后來直接拷貝整個Django工程到e盤相關路徑下,也是能正常工作的)

 

同時將在mysite2中看到一些和數據庫有關的文件

 

(4)創建視圖函數mysite2\disk\views.py

在這里我直接把demo.py稍加修改也一並放在這里了,詳情可看注釋,重點關注register()函數

# -*- coding:utf-8 -*-
#Author: Wu Jiang


import _init_paths       #導入路徑,調用faster_rcnn中相關模塊
from django.shortcuts import render,render_to_response
from django import forms         #Django表單方式上傳圖片
from django.http import HttpResponse
from disk.models import User                        
from fast_rcnn.config import cfg
from fast_rcnn.test import im_detect
from fast_rcnn.nms_wrapper import nms
#from utils.timer import Timer  by wj 11.3
import matplotlib.pyplot as plt   #matlab中畫圖工具
import numpy as np
import scipy.io as sio
import caffe, os, sys, cv2
import argparse
import sys
#from skimage import io,data   #11.19 by wj
#import shutil      #11.27 by wj  file
from os import listdir  #11.28 by wj    上述導入模塊有三個來源:一是views.py源文件、二是從demo中拷貝過來、三是為了后面讀寫文件操作

# Create your views here.
class UserForm(forms.Form):
    username = forms.CharField()
    headImg = forms.FileField()    
    
#直接從demo中拷貝來的
CLASSES = ('__background__',
           'aeroplane', 'bicycle', 'bird', 'boat',
           'bottle', 'bus', 'car', 'cat', 'chair',
           'cow', 'diningtable', 'dog', 'horse',
           'motorbike', 'person', 'pottedplant',
           'sheep', 'sofa', 'train', 'tvmonitor')
           
NETS = {'vgg16': ('VGG16',
                  'VGG16_faster_rcnn_final.caffemodel'),
        'zf': ('ZF',
                  'ZF_faster_rcnn_final.caffemodel')}
                  
def vis_detections(im, class_name, dets, thresh=0.5):
    """Draw detected bounding boxes."""
    inds = np.where(dets[:, -1] >= thresh)[0]
    if len(inds) == 0:
        return

    im = im[:, :, (2, 1, 0)]
    fig, ax = plt.subplots(figsize=(12, 12))     
    ax.imshow(im, aspect='equal')
    for i in inds:
        bbox = dets[i, :4]
        score = dets[i, -1]

        ax.add_patch(
            plt.Rectangle((bbox[0], bbox[1]),         
                          bbox[2] - bbox[0],
                          bbox[3] - bbox[1], fill=False,
                          edgecolor='red', linewidth=3.5)
            )
        ax.text(bbox[0], bbox[1] - 2,
                '{:s} {:.3f}'.format(class_name, score),
                bbox=dict(facecolor='blue', alpha=0.5),
                fontsize=14, color='white')

    ax.set_title(('{} detections with '
                  'p({} | box) >= {:.1f}').format(class_name, class_name,
                                                  thresh),
                  fontsize=14)
    plt.axis('off')
    plt.tight_layout()
    plt.draw()
    plt.savefig('test.png')   #圖片處理后保存下來

def demo(net, image_name):
    """Detect object classes in an image using pre-computed object proposals."""

    # Load the demo image
    #im_file = os.path.join(cfg.DATA_DIR, 'demo', image_name)
    im_file ='E:\\deep learning\\py-faster-rcnn-master\\tools\\mysite2\\upload\\000001.jpg'  #讀取該路徑下的000001.jpg圖片,每次上傳圖片之前都清空upload文件夾,保存新的圖片命名成000001.jpg
    im = cv2.imread(im_file)

    # Detect all object classes and regress object bounds
    #timer = Timer()  by wj 11.3
    #timer.tic()   by wj 11.3
    scores, boxes = im_detect(net, im)
    #timer.toc()   by wj 11.3
    #print ('Detection took {:.3f}s for '  by wj 11.3
           #'{:d} object proposals').format(timer.total_time, boxes.shape[0])   by wj 11.3

    # Visualize detections for each class
    CONF_THRESH = 0.8
    NMS_THRESH = 0.3
    for cls_ind, cls in enumerate(CLASSES[1:]):
        cls_ind += 1 # because we skipped background
        cls_boxes = boxes[:, 4*cls_ind:4*(cls_ind + 1)]
        cls_scores = scores[:, cls_ind]
        dets = np.hstack((cls_boxes,
                          cls_scores[:, np.newaxis])).astype(np.float32)
        keep = nms(dets, NMS_THRESH)
        dets = dets[keep, :]
        vis_detections(im, cls, dets, thresh=CONF_THRESH)

def parse_args_test():
    """Parse input arguments."""
    parser = argparse.ArgumentParser(description='Faster R-CNN demo')
    parser.add_argument('--gpu', dest='gpu_id', help='GPU device id to use [0]',
                        default=0, type=int)
    parser.add_argument('--cpu', dest='cpu_mode',
                        help='Use CPU mode (overrides --gpu)',
                        action='store_true')
    parser.add_argument('--net', dest='demo_net', help='Network to use [vgg16]',
                        choices=NETS.keys(), default='zf')

    args = parser.parse_args()

    return args


def register(request):
    if request.method == "POST":
        uf = UserForm(request.POST,request.FILES)
        #print sys.path
        if uf.is_valid():
            #獲取表單信息
            username = uf.cleaned_data['username']
            headImg = uf.cleaned_data['headImg']     #stand for dir or photo ??   request.FILES['file'] acquire photo  ?
            #寫入數據庫
            user = User()
            user.username = username
            user.headImg = headImg
            user.save()
            a=listdir('E:\\deep learning\\py-faster-rcnn-master\\tools\\mysite2\\upload')    #11.28 by wj
            old_file_path=os.path.join('E:\\deep learning\\py-faster-rcnn-master\\tools\\mysite2\\upload',a[0]) #11.28 by wj
            new_file_path='E:\\deep learning\\py-faster-rcnn-master\\tools\\mysite2\\upload\\000001.jpg'  #11.28 by wj
            os.rename(old_file_path, new_file_path)  #11.28 by wj   將保存下來的圖片改名成000001.jpg
            #shutil.copyfile('E:\deep learning\py-faster-rcnn-master\tools\mysite2\upload\000456.jpg','E:\deep learning\py-faster-rcnn-master\tools\mysite2\photo\000456.jpg')
            #shutil.copy(r'E:\deep learning\py-faster-rcnn-master\tools\mysite2\upload\000456.jpg','E:\deep learning\py-faster-rcnn-master\tools\mysite2\photo\000456.jpg')
            #io.imsave('E://deep learning//py-faster-rcnn-master//tools//mysite2//photo//000456.jpg',headImg) #11.19 wj
            #E://deep learning//py-faster-rcnn-master//tools//mysite2//photo//000456.jpg

            #return HttpResponse('upload ok!')   #can change it to show photos by wj   look related showing measures

            #if __name__ == '__main__':
            cfg.TEST.HAS_RPN = True  # Use RPN for proposals

            #args = parse_args_test()
            #args=Namespace(cpu_mode=False, demo_net='zf', gpu_id=0)

            #prototxt = os.path.join(cfg.MODELS_DIR, NETS[args.demo_net][0],
                           # 'faster_rcnn_alt_opt', 'faster_rcnn_test.pt')
            prototxt ='E:\\deep learning\\py-faster-rcnn-master\\models\\pascal_voc\\ZF\\faster_rcnn_alt_opt\\faster_rcnn_test.pt'
            #caffemodel = os.path.join(cfg.DATA_DIR, 'faster_rcnn_models',
                              #NETS[args.demo_net][1])
            caffemodel ='E:\\deep learning\\py-faster-rcnn-master\\data\\faster_rcnn_models\\ZF_faster_rcnn_final.caffemodel'

    #if not os.path.isfile(caffemodel):
        #raise IOError(('{:s} not found.\nDid you run ./data/script/'
                       #'fetch_faster_rcnn_models.sh?').format(caffemodel))   by wj 17.11.8

    #if args.cpu_mode:
            caffe.set_mode_cpu()
    #else:
        #caffe.set_mode_gpu()
        #caffe.set_device(args.gpu_id)
        #cfg.GPU_ID = args.gpu_id
            net = caffe.Net(prototxt, caffemodel, caffe.TEST)

    #print '\n\nLoaded network {:s}'.format(caffemodel)  by wj 17.11.8

    # Warmup on a dummy image
            im = 128 * np.ones((300, 500, 3), dtype=np.uint8)
            for i in xrange(2):
                 _, _= im_detect(net, im)

    #im_names = ['000456.jpg', '000542.jpg', '001150.jpg',  by wj 11.3
               # '001763.jpg', '004545.jpg']   boy wj 11.3
            im_names = ['000001.jpg']   #固定處理名為000001.jpg的圖片

            for im_name in im_names:
        #print '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'  by wj 17.11.8
        #print 'Demo for data/demo/{}'.format(im_name) by wj 17.11.8
        #print args   how to change this
                demo(net, im_name)
            #plt.savefig('test.png')
            #plt.show()
            os.remove(new_file_path)   #11.28 by wj    在上傳新的圖片前清空upload文件夾,是每次demo處理時upload里只有一張名為000001.jpg圖片
            #os.remove('E:\\deep learning\\py-faster-rcnn-master\\tools\\mysite2\\test.jpg')
            #return HttpResponse('upload ok!') #11.29 by wj 
            imagepath ='E:\\deep learning\\py-faster-rcnn-master\\tools\\mysite2\\test.png'
            image_data = open(imagepath,"rb").read()  
            return HttpResponse(image_data,content_type="image/png") 
    else:
         uf = UserForm()
    return render_to_response('register.html',{'uf':uf})

(5)創建模板文件

在mysite2/disk/目錄下創建templates文件夾,接着在mysite2/disk/templates/目錄下創建register.html 文件

添加內容如下:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <title></title>
</head>
<body>
<h1>faster_rcnn</h1>
<form method="post" enctype="multipart/form-data" >
{{uf.as_p}}
<input type="submit" value="ok"/>
</form>
</body>
</html>

不用按參考blog中提到的設置模板路徑,Django1.8版能夠自動找到

(6)設置URL

打開mysite2\mysite2\urls.py

from django.conf.urls import include, url
from django.contrib import admin
from disk import views as disk_views 

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    #url(r'^disk/$', disk_views.register),
    url(r'^$', disk_views.register),
]

(7)啟動服務

cmd模式下cd到Django工程mysite2(第一級mysite2)的路徑,輸入命令Python manage.py  runserver  啟動服務器,有可能會拋出相應錯誤,具體解決辦法見參考blog,正常成功情況下應顯示如下界面,並能上傳圖片到自己新建的upload文件夾。(upload文件夾需要新建,路徑參考下面截圖)

 

 

Django最主要的幾個文件是urls.py、views.py、html、models.py文件,在這里我簡要介紹一下上述代碼的執行過程

首先,我們來看urls.py文件

重點看我標注的這一句,urls文件表明當用戶訪問http://127.0.0.1:8000/ 時將調用views.py中定義的register函數

接着,我們看一下html文件內容

學過html相關概念的人應該能讀懂這段,但這里有句{{uf.as_p}}讓人很難理解意思,uf是建立的user數據庫,用戶輸入后將在這里填充相關數據。當顯示登錄界面時,請在瀏覽器工具欄—工具----查看源代碼可以看到網頁信息如下,比較上下區別,就可以弄懂啦!

接下來關注views.py視圖函數,這里定義了一些Django工程中的核心函數。(下圖只包含了部分內容)

這里我主要想講解一下這段代碼的執行順序,當我們輸入網址登錄網頁時,這時request.method還不是post方式,所以執行的是else下的代碼,返回了一個html文件,並且在原始文件中{{uf.as_p}}填充了uf的一些輸入要求,比如type,這可以在上面的源文件中看到。render_to_response() 的第一個參數必須是要使用的模板名稱。 如果要給定第二個參數,那么該參數必須是為該模板創建 Context 時所使用的字典。之后,當我們輸入了username、選擇圖片后點擊OK,這時將變成post方式,執行if語句,返回httpresponse對象,顯示upload ok,這時文件夾upload里就會保存剛才上傳的圖片。至此以form表單方式上傳文件機制介紹完了,實際上還有更簡單的文件上傳機制,比如文件流的方式,只是當時我沒調通,所以沒有細究。除此以外,將選擇的圖片經過demo處理后需要再在網頁上顯示處理結果,這里我投機取巧找到一個文件流的顯示方式,具體見代碼,返回了一個httpresponse對象。才疏學淺,完成的較為粗糙,點擊這里可下載完整代碼,提取碼1qh1,py-faster-rcnn工程請參考本人這篇blog

四、本文faster rcnn demo程序的適應性修改與關鍵地方講解

現在服務器、后台能夠接受到用戶傳來的圖片,所以我們很自然的想到下一步任務就是把demo的關鍵處理代碼拷貝到Django工程下的views.py文件(前面已經給出完整的views.py)。因此需要修改一些地方,faster_rcnn的模塊調用要理順。首先需要將E:\deep learning\py-faster-rcnn-master\tools中的_init_paths.py文件修改成如下圖,並拷貝到如下路徑,主要是為了使添加上述代碼后的views.py執行時能找到faster_rcnn的相關文件,為方便處理,我直接給出了相應模塊、py文件的完整路徑。其中os.join函數是個拼接路徑函數,路徑的正確格式也是我打斷點調試才知道的。

 

# --------------------------------------------------------
# Fast R-CNN
# Copyright (c) 2015 Microsoft
# Licensed under The MIT License [see LICENSE for details]
# Written by Ross Girshick
# --------------------------------------------------------

"""Set up paths for Fast R-CNN."""

import os.path as osp
import sys
import os

def add_path(path):
    if path not in sys.path:
        sys.path.insert(0, path)

#this_dir = osp.dirname(__file__)
#this_dir = os.getcwd()
# Add caffe to PYTHONPATH
#caffe_path = osp.join(this_dir, '..', 'caffe-fast-rcnn', 'python')
# E:\deep learning\py-faster-rcnn-master\caffe-fast-rcnn\python
caffe_path = 'E:\\deep learning\\py-faster-rcnn-master\\caffe-fast-rcnn\\python'
#caffe_path = osp.join(this_dir, '..','..','..', 'caffe-fast-rcnn', 'python')
#caffe_path = osp.join(this_dir, '/../../..', 'caffe-fast-rcnn', 'python')
add_path(caffe_path)

# Add lib to PYTHONPATH
#lib_path = osp.join(this_dir, '..', 'lib')
#E:\deep learning\py-faster-rcnn-master\lib
lib_path ='E:\\deep learning\\py-faster-rcnn-master\\lib'
#lib_path = osp.join(this_dir, '..','..','..', 'lib')
#lib_path = osp.join(this_dir, '/../../..', 'lib')
add_path(lib_path)

關於views.py,我想在這里補充一下我投機取巧的地方,一是一些關鍵地方,比如模型文件、圖片等的路徑我直接給出了完整路徑,並且代碼的確很粗糙。另外,利用form表單上傳圖片我在后台不知道如何取相應的圖片,所以我采用的方法是:由於我知道圖片會保存在upload文件夾里,每次將不同名字的圖片保存后,我首先將圖片改名成000001.jpg,這樣就能被demo處理,處理完后生成test.png后清空upload文件夾里的圖片,保存處理后的test.png顯示在網頁上。

另:Django工程是可以在pycharm中打斷點調試的!!!具體debug調試可參考blog,在views.py打斷點,用戶在前端選擇圖片點ok后可以在pycharm中看到變量值。建議讀者再進一步優化代碼,同時有些絕對路徑根據讀者存放位置進行修改。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM