---做者吳疆,未經容許,嚴禁轉載,違權必究---html
---歡迎指正,須要源碼和文件可站內私信聯繫---前端
-----------點擊此處連接至博客園原文-----------python
功能說明:利用Python web框架Django,將faster-rcnn的demo程序以網頁形式展示出來,簡而言之是基於B-S架構的編程,直觀地以網頁形式展現目標檢測的功能。linux
運行環境:Window7 cpu Python2.7 Pycharm5.0 Django1.8xweb
1、功能預覽數據庫
首先,啓動服務器,將返回一個網址: http://127.0.0.1:8000/ 即本機地址 (模擬網頁,本機同時是服務器和模擬前端用戶)django
而後,咱們能夠登陸上面給出的地址編程
接着,咱們輸入相關內容,點擊ok瀏覽器
等待網頁返回處理後的結果(樓下俺的女友)服務器
能夠看到此時後臺在執行faster rcnn相關代碼
若是想復現上述功能,請按本人寫做順序依次進行相關操做。
2、Django環境的搭建
參考連接:Django自學之路
以本人Windows7系統爲例看上述參考連接中Django環境搭建2.1.2部分,建議選Django1.8版本,便於後續學習。建議自主學習本網址Django視圖與網址部分,半小時就能理解。大體能對新建Django工程、工程目錄下應有什麼文件、以及主要的一些文件如views.py、urls.py的做用有個清晰的理解,這些內容仍是靜靜地學習這個網址的講解,後文我也會說起一部分。如下是本人安裝Django的簡要筆記,大略能夠參考一下。
3、本文Django工程中的文件上傳機制
參考這篇博客,其基於deepin linux 201三、Python 2.七、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。
4、本文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中看到變量值。建議讀者再進一步優化代碼,同時有些絕對路徑根據讀者存放位置進行修改。