我的AI之路(43)--使用百度pyramidbox口罩識別模型

        想試用百度的口罩識別模型的可以往下看看,這個公開的模型對我已經用不着了,所以後續如果百度有更新我也沒跟進了,因爲它目前仍存在泛化性差有時誤識別挺頻繁的問題(比如識別黑色口罩時很容易出錯,側臉也容易出錯),由於是免費的,也不好催促人家解決,也好像還沒開放用自己的數據集做增量訓練的接口,由於防疫機器人項目進度緊,所以乾脆自己找了了數據集再加上發動公司同事春節後在家上班期間集體收集的一些圖片標註了作爲補充,讓熟悉標註的同事對標註做了一遍檢查剔除掉標註不準確和容易引起誤識別的數據,然後使用了個高精度且高性能的模型訓練後做了調用封裝,用於防疫消殺機器人上,據負責應用開發的同事反映,比百度的口罩模型在非白口罩的識別和側臉識別等方面誤識別少多了並且性能比百度的還好,識別效果回放比較流暢。

[原文]

       疫情特殊時期百度大廠展現社會責任感,組織團隊加班加點基於他們自己的人臉識別模型pyramidbox弄出了準確率比較高的口罩識別模型,安裝paddlepaddle和paddlehub後就可把模型下載到本地免費使用,模型有server版還有mobile版,並且提供了python調用示例代碼,這個很贊。

       據說騰訊優圖也弄出了識別口罩佩戴準確率99%的模型,正在準備上線到雲服務,期待兩家的都試用一下PK一下看哪家更牛用哪個,有免費瓜喫我們喫瓜羣衆當然樂於等着試喫...

      百度的口罩識別模型上週公開,因項目急需,我本週一開始安裝部署試用,第一版模型試用對正面識別比較準,側臉就基本全錯,百度的團隊也在趕工提升模型和paddlehub,週四更新到第二版,測試發現側臉識別基本可以了,進展也挺神速的,贊啊,不過試用過程中遇到了若干問題,提交給了百度的大牛,迅速做了解決和更新,現在支持GPU的版本基本上可用了,用於演示已經應該差不多了,只是性能還有待提升點,目前在我們的服務器上使用GPU版,識別一張1M多的圖需要1.5-2秒,按理說雖然RTX2080TI GPU比不上Telsa v100那樣的,但算力也算不錯了,性能這點感覺百度模型或者paddlehub封裝程序還有待提升的地方,大廠的團隊後面能持續改進一下就很讚了。不過話說回來,免費的瓜還有啥好計較的,看跟我對接的老師/大牛也是在線工作到很晚還在回答我提交的問題,改正hub錯誤的地方發改好的版本給我試用,技術人尤其熱愛技術的人都不容易啊,就算公司沒要求加晚班自己也會手癢停不下來,哈哈...

     記錄一下怎麼安裝百度的paddlepaddle和paddlehub以及口罩識別模型:

    百度的paddlepaddle官網https://www.paddlepaddle.org.cn/上面提供了類似pytorch那樣的安裝環境配置選擇的界面,很方便,根據你需要安裝的環境選擇OS、Python版本、CUDA版本以及安裝方式(pip、conda、docker、build from source),選好後下面會出現對應的一條或多條命令,拷貝這些命令依次執行就行了。

      安裝方式我現在每次都毫不猶豫的選擇docker,爲麼? 對於安裝環境所在的機器上,如果只打算安裝部署一種模型或框架,那麼安裝python後使用pip安裝到默認路徑下就行了,如果打算使用多個不同框架(tensorflow/pytorch/caffe/paddlepaddle...,到目前爲止我只用過這四種,其他的微軟和亞馬遜的沒用過,但看過一點示例代碼感覺搞法都相似差不多)以及多種不同模型的訓練環境,個人機器上用用,可以考慮使用conda建立隔離環境,分開安裝也基本上能對付了,但是對於公司的企業級部署環境,conda顯然不能滿足要求,爲麼呢?conda不支持拷貝發佈,換臺機器都得安裝一遍,你說煩不煩 時間和人力成本高不高,企業級部署當然最好使用docker了,現在的主流深度學習框架都有對應的docker文件不斷的更新,拉取對應的版本的image後,創建個實例跑起來,裏面框架和相關的必要支持包都給你安裝好了,省了大把的安裝和解決安裝遇到問題的時間,在docker實例上把模型訓練或者運行的環境安裝好後commit出一個新的image後,就可以在很快在其他安裝了docker服務的機器上跑起來,其他什麼都不用安裝了,這節省了大把時間。同時,同一臺服務器上,不同的框架/模型跑在不同的docker實例裏,互不干涉,沒有支持包版本不兼容衝突之類頭疼的問題(有過在同一環境下安裝過多個模型環境經歷的 一定會對numpy版本不兼容之類引起的錯誤深惡痛絕 ^_^ ),多好。

      

     根據我的環境選擇Ubuntu、docker、Python3、CUDA10後拷貝下面的命令到服務器上執行:

         nvidia-docker pull hub.baidubce.com/paddlepaddle/paddle:1.6.3-gpu-cuda10.0-cudnn7

     等下載完畢後,執行docker images,可以看到大小有12.3G的image:

         hub.baidubce.com/paddlepaddle/paddle   1.6.3-gpu-cuda10.0-cudnn7       e3895a23df3d

     然後執行下面的命令創建和運行實例(映射的端口8866是爲模型以server方式部署時準備的):

        nvidia-docker run --name paddle -it -v /home/arnold/AI/pphub:/paddle -p 8866:8866  hub.baidubce.com/paddlepaddle/paddle:1.6.3-gpu-cuda10.0-cudnn7 /bin/bash

      實例啓動後進入python3.5,並驗證paddlepaddle可運行:
         import paddle.fluid
         paddle.fluid.install_check.run_check()

      提示你安裝成功或者提示只能用單機版:Your Paddle Fluid is installed successfully ONLY for SINGLE GPU or CPU! 中間報錯一大堆說什麼NCCL沒安裝之類的可以不理 ,就可以用了,如果你不需要使用多GPU做分佈式訓練的話。

     如果要安裝NCCL的話,執行下面的命令安裝2.4.8-1版nccl,不要安裝最新的2.5.6-1版,因爲paddlepaddle docker裏安裝的就是2.4.8-1,看來這個版本是沒有兼容性問題的,盲目安裝高了就出現NCCL沒安裝之類的這樣那樣的報錯:

            sudo apt install libnccl2=2.4.8-1+cuda10.0 libnccl-dev=2.4.8-1+cuda10.0

 

     下面安裝調用口罩識別模型所需的paddlehub,先更新一下pip和setuptools,否則安裝過程中可能會報錯:

            pip3 install --upgrade pip 
            pip3 install --upgrade setuptools

            pip3 install   paddlehub

       安裝完了paddlehub,再安裝一下 vim(必須品)和git(可選,下載源碼才需要)之類的工具:

            apt-get install vim

       paddlepaddle和paddlehub都安裝好了,那麼怎麼下載模型呢?下載模型隱藏在代碼裏!不能單獨執行命令下載。

     

       模型可以部署到本地使用代碼直接調用,也可以使用paddlehub部署成http server 模式供客戶端遠程訪問,客戶端代碼使用http post調用,要識別的圖片在post中上傳。

下面寫調用測試代碼(這些代碼參考百度官網,根據自己情況改寫一下就行了),下面是本地直接調用模型識別圖片的代碼:

         import paddlehub as hub
         import paddle.fluid

         import cv2
         import os

        os.environ["CUDA_VISIBLE_DEVICES"]="0"   # 推理時想要用到GPU的話一定要有這句話,不然只是要CPU,我覺得這裏有點怪,自己去找0號GPU不就行了,猜測可能是CUDA沒有提供判斷GPU是否被佔用的接口?所以paddle只能要求這麼幹了

       #下載(已下載則略過)模型並創建實例,模型文件被下載存放到/root/.paddlehub/modules/下,pyramidbox_lite_mobile_mask用於嵌入式環境,pyramidbox_lite_server_mask用於PC環境,但實際上兩個模型都可以在PC上跑:

     #hub install pyramidbox_lite_server_mask==1.2.0

     hub install pyramidbox_lite_mobile_mask==1.2.0

 

       module = hub.Module(name="pyramidbox_lite_mobile_mask",version='1.2.0')  
       #module = hub.Module(name="pyramidbox_lite_server_mask", version='1.2.0')

       img_path="/paddle/drdkz/dr-2.jpg"

       img=[img_path]
       input_dict = {"image": img}
       results = module.face_detection(data=input_dict,use_multi_scale=True, shrink=0.6,use_gpu=True,use_cuda=True)  #使用GPU時需要加這些紅色參數

       for result in results:
           print(result)  

      或者:

      img_path=["/paddle/drdkz/dr-2.jpg"]

      img_data = [cv2.imread(img) for img in img_path]

      results=module.face_detection(data={"data":img_data},use_gpu=True,use_cuda=True) #使用GPU時需要加這些紅色參數

      for result in results:
           print(result) 

     本地直接調用模型需要自己根據結果數據把在圖中把標註框畫出來:

      img = cv2.imread(img_path)
      for result in results:
          print(result)
          data =result['data']
          x_min=int(data['left'])
          y_min=int(data['top'])
          x_max=int(data['right'])
          y_max=int(data['bottom'])
          #print(x_min,y_min,x_max,y_max)
          text=data['label']+" "+ str(round(float(data['confidence']),2))
          cv2.rectangle(img,(x_min,y_min),(x_max,y_max),(0,255,0),3)
          cv2.putText(img, text,(x_min,y_min),cv2.FONT_HERSHEY_COMPLEX,0.6,(0,0,255),1)
          path,file = os.path.split(img_path)
          img_out =  path + os.path.sep + "/checked/"+file
          cv2.imwrite(img_out,img)

   對於使用paddlehub把模型部署到sever端供遠程使用http post調用,非常簡單,服務端執行(使用GPU需要加上紅色部分):

         export CUDA_VISIBLE_DEVICES=0

         hub serving start -m pyramidbox_lite_server_mask -p 8866 --use_gpu --use_singleprocess 

   服務啓動後在8866監聽(前面在啓動docker時對此端口對外做了映射以邊docker容器外部訪問),然後客戶端調用測試代碼使用:

       import requests
       import json
       import base64
       import os


      file_list = ["drdkz/dr-1.jpg"]
      files = [("image", (open(item, "rb"))) for item in file_list]
      url = "http://127.0.0.1:8866/predict/image/pyramidbox_lite_server_mask"
      r = requests.post(url=url, files=files)  #如果不需要response中包含識別結果圖片的base64數據和文件的path,則

                                                                 #加上參數 data={"visual_result": "False"},默認包含
      results = eval(r.json()["results"]
      print(results)
      if not os.path.exists("output"):
         os.mkdir("output")
     for item in results:
         with open(os.path.join("output", item["path"]), "wb") as fp:
             fp.write(base64.b64decode(item["base64"].split(',')[-1]))
             item.pop("base64")
     print(json.dumps(results, indent=4, ensure_ascii=False))
   

注意這裏要識別的文件是以二進制方式上傳的,使用其他語言編寫時以form的upload方式上傳文件即可:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章