iT邦幫忙

2021 iThome 鐵人賽

DAY 22
0
AI & Data

觀賞魚辨識的YOLO全餐系列 第 22

Day 22 - Django + YOLO 後台整合應用

Day 22 - Django + YOLO 後台整合應用

今天的任務是將 Day 07 - RESTful API 在 Amazon Linux 2 上傳圖片實作Day 08 - Amazon Linux 2 上將 Django 與 Nginx 整合Day 09 - Amazon Linux 2 上解決跨來源資源共用 (CORS) 與開機自動啟動 uwsgi 這三天完成的 Django 後端結合 Day 14 - 安裝與執行 YOLO 的 Joseph/darknet ,這樣就可以完成觀賞魚辨識系統的完整後端應用。

下圖是觀賞魚辨識系統的泳道圖,因為每個系統之間都是獨立運行,所以透過泳道圖來表示各系統之間的關係是比較適合,後端的部份是從 Nginx, Django, YOLO 模型和資料庫所組成,當我們要整合後端時必須知道各元件之間的相互關係跟流程:

  1. Django 建立 RESTful API,並載入 YOLO 事先訓練好的權重與網路架構組態。
  2. Django 收到 Nginx 的請求後,需要儲存圖片,接著通知 YOLO 去辨識圖片,並將結果寫入處理後的圖片,並回傳辨識的結果。
  3. Django 得到辨識結果後,會去資料庫中得到詳細數據,接著將結果以 JSON 的格式回傳給手機端/網頁端。
  4. 手機端/網頁端得到 JSON 回應後,分析回應並顯示結果。

https://ithelp.ithome.com.tw/upload/images/20210922/20129510SNSxd2ZFbQ.png
圖 1、觀賞魚辨識系統泳道圖

在 Django 載入 YOLO 事先訓練好的權重與網路架構組態

因為我們需要事先載入 YOLO 事先訓練好的權重與網路架構組態,這可以減少不必要的時間浪費,我們就這段代碼寫的 Django 的 view.py,可參閱 Day 07 - RESTful API 在 Amazon Linux 2 上傳圖片實作,但在撰寫代碼之前必須先把相關環境設定好,下圖是目前的相關路徑,最上層是 Python 的虛擬環境 fishRecognition,下一層是 Django 專案 fishsite (外層),然後我們在專案的目錄下放了 Joseph/darknet 的 YOLO 模型以及我們自建的觀賞魚數據集,而主要程式區則是放在 fishsite(內層) APP 這個目錄下,但因為所有匯入 (import) 的起始目錄是在 fishsite (外層),所以我們把需要用到的文件夾都在這個目錄下建立捷徑,包含了 libdarknet.so, cfg/, data/, weights/ 。

https://ithelp.ithome.com.tw/upload/images/20210922/20129510KkUjtHeHcM.png
圖 2、Django 專案區的文件夾結構

fishsite/view.py 中新增載入 YOLO 事先訓練好的權重與網路架構組態的語法,下圖是部分代碼截圖。

fishsite/view.py

import darknet.python.darknet as dn
import cv2
import time
import numpy as np
import urllib.parse
print('load view model')

net = dn.load_net(str.encode("./FishRecognition/cfg/yolov3.cfg"),
                  str.encode("./FishRecognition/weights/yolov3.backup"), 1)
meta = dn.load_meta(str.encode("./FishRecognition/cfg/obj.data"))

https://ithelp.ithome.com.tw/upload/images/20210922/201295104ubB2mMFP0.png
圖 3、view.py 的部份代碼截圖

運行 Django,因為埠號 8000 已被佔用,所以選擇 8080,結果如下圖。

python3 manage.py runserver 0.0.0.0:8080

https://ithelp.ithome.com.tw/upload/images/20210922/20129510Z1qic4mcMM.png
圖 4、運行 Django 的結果

呼叫 YOLO 辨識圖片

這段代碼需要完成:呼叫 YOLO 辨識圖片;處理辨識後結果;畫方塊框與寫入名稱,並產生處理後圖片;查詢資料庫,並回傳 JSON 結果。

fishsite/view.py

    def post(self, request, *args, **krgs):
        print('FishView->post')
        uploadFile = request.FILES.get('fileUpload')
        # write the uploaded file into the server
        filename = r'upload/{}'.format(uploadFile.name)
        with open(filename, 'wb') as f:
          for chunk in uploadFile.chunks():
            f.write(chunk)
        print('FishView->upload')
        # 呼叫 YOLO 辨識圖片
        prev_time = time.time()
        pridictStr = dn.detect(net, meta, str.encode(filename))
        print((time.time() - prev_time))
        # 處理辨識後結果
        cv2image = cv2.imread(filename)
        if len(pridictStr) > 0:
        # 畫方塊框與寫入名稱,並產生處理後圖片
          for k in range(len(pridictStr)):
            print(pridictStr[k])
            print(pridictStr[k][2])
            x, y, w, h  = pridictStr[k][2]
            text = pridictStr[k][0].decode('utf-8')
            x = int(x - w/2)
            y = int(y - h/2)
            cv2.putText(cv2image, "{} {:.4f}".format(text,pridictStr[k][1]), (x, y-6), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 1, cv2.LINE_AA)
            cv2.rectangle(cv2image, (int(x),int(y)), (int(x+w),int(y+h)), (0,255,0), 2)
          cv2.imwrite(r'upload/new_{}'.format(uploadFile.name), cv2image)
        # 查詢資料庫,並回傳 JSON 結果
          sql = "SELECT fishName, distribution, LatinName FROM fishInfoTbl WHERE LatinName='{}'".format(pridictStr[0][0].decode('UTF-8'))
          with connection.cursor() as cursor:
            cursor.execute(sql)
            data = dictfetchall(cursor)
          print('FishView->' + sql)
          data[0]['fishQtn']=len(pridictStr)
          data[0]['processImg'] = 'http://18.138.102.108/images/new_{}'.format(urllib.parse.quote(uploadFile.name))
        else:
          data = dict({"error": "cannot recognize it"})
        return JsonResponse(data,safe=False)

本段代碼無法處理一張圖片中有多個不同物件,需要再自行修改。

使用 Advanced REST Client

修改完 fishsite/view.py REST API 部分,重新的運行 Django。

python3 manage.py runserver 0.0.0.0:8080

然後在前端使用 Advanced REST Client 來呼叫 REST API ,呼叫結果如下圖,上傳一個 00-frame-608x608-0002.jpg 的圖片,回傳的結果就是辨識的內容,並且會回傳處理後的圖片所在位置,這樣方便前端顯示結果文字及圖片。

https://ithelp.ithome.com.tw/upload/images/20210922/20129510cc8o3zsZqP.png
圖 5、運行 Django 的結果

參考資料


上一篇
Day 21 - 嵌入 AlexeyAB/darknet 的 Python
下一篇
Day 23 - 前端開發工具 - HBuilder X
系列文
觀賞魚辨識的YOLO全餐38

尚未有邦友留言

立即登入留言