# YOLO3的安裝與實作
取材於[Jason Hung第 11 屆 iT 邦幫忙鐵人賽的](https://ithelp.ithome.com.tw/users/20120243/ironman/2404?page=2)19-21天
物件偵測(Object Detection)是指在照片或影片等圖像內容中,用框標出物件的範圍,並且分類為何種物件及他的猜測機率。
物件的偵測可以運用在很多產業,像有人用他來辨識黃瓜。
[日本農夫](https://chtseng.wordpress.com/2016/09/09/%E6%B7%B1%E5%85%A5%E5%AD%B8%E7%BF%92%E7%9A%84%E6%87%89%E7%94%A8-%E6%97%A5%E6%9C%AC%E7%9A%84%E5%B0%8F%E9%BB%83%E7%93%9C%E8%BE%B2%E5%A0%B4/)
勵志的日本黃瓜農夫,如何用 Google 深度學習 AI 改善農場人生?
引入了 Google 的深度機器學習系統,搭配了圖像辨識與分類學習系統後,製作了一條自動化分類輸送帶,只要事前準備好一批已經分類好的黃瓜,並且拍成照片、標上等級後建檔,交給機器學習模組,之後 AI 就可以透過學習而來的資料,快速且準確的在自動化分類輸送帶上幫助分類。
用來辨識雜草
[美國農機老店](https://ai-blog.flow.tw/ai-in-agriculture)
180 年農機老店,要用 AI 跟雜草開戰
運用電腦視覺和機器學習來偵測、分辨雜草,並做出管理決策。與其漫天噴灑農藥,「看見再噴」(see and spray)的技術,就像手術刀一樣精準,切除每棵病灶。不僅減少90%的農藥用量,還可提高產量。
如果不要涉及隱私方面,電腦視覺是很強大的應用方向。
物件偵測(Object Detection)演算法有
R-CNN
Fast R-CNN
Faster R-CNN
Mask R-CNN
YOLO
SSD
[YOLO的官網](https://pjreddie.com/darknet/yolo/)
[Joseph Redmon在TED的演說](https://www.youtube.com/watch?v=Cgxsv1riJhI)How computers learn to recognize objects instantly
片長7分37秒
yolo 是學習起來成就感很強的演算法,要弄懂可能不太容易,但是照著官網上的步驟,要實作一個 Demo 還蠻容易成功的。當你可以即時看到他呈現的樣子,在圖片或影片或鏡頭下,看著框追蹤著物體跑,感覺很神奇。
我們先看看他可以辨識出什麼物品,這樣你才能知道要丟什麼照片給他看阿。他預處理的權重,是用 COCO 資料集,COCO數據集網站有列出蠻多特色,不過我們只要先知道他有80種類別就行了,那80種呢? 有興趣可以先看這個檔 coco.names,下面就簡單的把80個種類再分類一下,比較好記。
[coco資料集](http://cocodataset.org/#home)
交通方面
人 / 自行車 / 汽車 / 摩托車 / 飛機 / 巴士 / 火車 / 卡車 / 船
紅綠燈 / 消防栓 / 停止標誌 / 停車收費表 / 板凳
動物方面
鳥 / 貓 / 狗 / 馬 / 羊 / 牛 / 象 / 熊 / 斑馬 / 長頸鹿
配件方面
背包 / 雨傘 / 手提包 / 領帶 / 手提箱
運動用具
飛盤 / 滑雪板 / 單板滑雪 / 運動用球 / 風箏 / 棒球棒 / 棒球手套 / 滑板 / 衝浪板 / 網球拍
廚房方面
瓶子 / 紅酒杯 / 杯子 / 叉子 / 刀 / 勺 / 碗
食物方面
香蕉 / 蘋果 / 三明治 / 橙子 / 西蘭花 / 胡蘿蔔 / 熱狗 / 比薩 / 甜甜圈 / 蛋糕
家具方面
椅子 / 沙發 / 盆栽植物 / 床 / 餐桌 / 馬桶
電視監視器 / 筆記本電腦 / 滑鼠 / 搖控器 / 鍵盤 / 手機
微波 / 烤箱 / 烤麵包機 / 水槽 / 冰箱
書 / 時鐘 / 花瓶 / 剪刀 / 泰迪熊 / 吹風機 / 牙刷
yolo 會成為熱門的演算法是因為他偵測速度很快,為什麼很快,網站有稍微說明一下。
先前的檢測系統重新利用分類器或定位器來執行檢測。將模型應用於多個位置和比例的圖像。圖像的高分的區域被認是檢測的區塊。YOLO使用完全不同的方法。我們將單個神經網路應用於完整圖像。該網路將圖像劃分為多個區域,並預測每個區域的邊界框和概率。邊界框會由預測的概率進行加權。
與基於分類器的系統相比,YOLO的模型具有多個優勢。它在測試時查看整個圖像,因此其預測由圖像的全局中的相關網格提供。它不像R-CNN這樣的系統需要單個網路評估來進行預測,而R-CNN單個圖像需要數千個。這使其變得非常快,比R-CNN快1000倍以上,比Fast R-CNN快100倍。
可參考這篇
[物體偵測(Object Detection) + 影像標題(Image Captioning)](https://ithelp.ithome.com.tw/articles/10192950)
標註區域的方式有下列幾類演算法:
1.滑動視窗(Sliding Window)
這是一種窮舉法,設定各種尺寸的區域,從左上角開始滑動,找出所有區域,然後,看哪一個區域符合的機率最高。這種方法最簡單,但是也相對耗時。
2.候選區域(Region Proposals)
利用了圖像中的紋理、邊緣、顏色等信息,人為定義可能含有目標的RoI(Regions of Interest)區域,只針對這些區域比較符合的機率,每秒可過濾上千個區域,相關演算法有 R-CNN、Fast R-CNN、Faster R-CNN...等。
3.迴歸方法
將圖片切成小方塊(Grid),再以小方塊中心點選擇幾種尺寸的區域,利用迴歸方法計算每個區域含有目標的機率。這種方法較 Region Proposals快,更適合即時(Real Time)偵測,目前相關演算法有有 YOLO(You Only Look Once)、SSD(Single Shot MultiBox Detector)...等。
所以到這裡,我們會知道2件事,第一是 yolo3 為什麼很快的原因。第二是使用 yolo3 的已訓練好的權重可以辨識80種類的物品。當然你可以再加上資料訓練去擴充他的種類,或是完全改用自己的分類。不過 yolo3 也有缺點,因為他是把整張圖去切格子,所以你東西太小的話,他辨識率不高。
[<font color=redblue>Tao:應該是yolo2的缺點;yolo3就是來改善這一點的</font>]
開始介紹 YOLO 的實作練習,一般建立環境當然是建在我們的本地的電腦上,建好後會很方便操作。不過有時因為每個人的電腦環境不太一樣,雖然說安裝步驟其實沒有很難,但是很有可能會在自己的電腦裝弄天,搞定環境後都快去掉半條命了。
今天我們可以更簡單一點,不用自己準備機器。我們就直接用 Google colab 來玩, 你只要有 Google 帳號就可以開始了。是不是很心動,哈。
首先要感謝這個作者 David Ibáñez,真心崇拜這位作者,好用心把程式整理分享。我練習後,發現真的很方便教學。而且也強化了我 Google colab 的技能。這個練習主要是參考 David Ibáñez 這篇教學。
* [David Ibáñez的原版 ](https://colab.research.google.com/drive/1lTGZsfMaGUpBG4inDIQwIJVW476ibXk_)
* [在PYTHON程式中使用YOLO](https://chtseng.wordpress.com/2018/10/08/%E5%A6%82%E4%BD%95%E5%9C%A8python%E7%A8%8B%E5%BC%8F%E4%B8%AD%E4%BD%BF%E7%94%A8yolo/)請參考這篇
我已經將程式碼放在雲端硬碟中,可直接複製到屬於你的colab上執行.
[YOLOv3安裝與實做.ipynb](https://colab.research.google.com/drive/16kXIvnz2gNk8jOz_4KB5pl3XLZR79WSd?usp=sharing)
### Part 1 安裝yolov3
那我們開始吧.
第1步:
建立jupyter筆記本,就是在你的 Google Colab 新建一個 Python3 筆記本,並且設定為使用有GPU的伺服器。
第2步:
與雲端硬碟連接
因為 colab 時間到了會清掉你的檔案,所以要跟雲端硬碟連接,用來存放我們需要的檔案。
```python=
from google.colab import drive
drive.mount('/content/gdrive')
```
在執行時他會給你一個連結還有一個輸入框,點連結下去後會需要先登入帳號,同意授權,之後會出現金鑰,像這像(4/rwFnMDkRAYND2a1r6ktfVqPnoLE61ichB...),再把這串貼到下面的輸入框按 Enter,看到這個訊息就是連接成功了。
"Mounted at /content/gdrive"
第3步: 安裝 cuDNN
3-1 先檢查 CUDA 版本
```python=
!/usr/local/cuda/bin/nvcc --version
```
你應該會看到版本號, 如"Cuda compilation tools, release 10.0, V10.0.130" 表示是第10版號
3-2 依目前的 CUDA 版本號, 安裝 cuDNN
去 Nvidia 官網下載
[Nvidia](https://developer.nvidia.com/cudnn),它沒法直接下載,應該需要填一些資料加入為會員。我下載時檔名是長這樣 cudnn-10.0-linux-x64-v7.6.2.24.tgz,下載後先把它上傳到雲端硬碟上,我們等一下會用到它。如下圖,我是放在 darknet/cuDNN 目錄下面.

<font color=red>這段需要處理路徑</font>
3-3 解壓縮tgz,把檔案放到 /usr/local/
這裡說明一下路徑
gdrive :是我們剛連接的根目錄
/My\ Drive :是我們雲端硬碟目錄
/darknet/cuDNN/ :是我們建立的目錄
連起來就是 gdrive/My\ Drive/darknet/cuDNN/
```python=
!tar -xzvf gdrive/My\ Drive/darknet/cuDNN/cudnn-10.0-linux-x64-v7.6.2.24.tgz -C /usr/local/
!chmod a+r /usr/local/cuda/include/cudnn.h
```
第4步:
下載及編譯 darkent (只需要一次)
再來是編譯 darkent , 只有第一次執行才需要,如果你成功編譯完,把編譯完的檔案存到你的雲端硬碟後,你下次再執行,就不用再執行這一個步驟了。只需要把雲端硬碟的檔案複製過來就好。
```python=
!git clone https://github.com/kriyeng/darknet/
%cd darknet
!ls
!git checkout feature/google-colab
```
接著編譯它
```python=
!make
```
把編譯完的 darknet檔,複製到雲端硬碟的 darknet/bin/darknet
先在你的雲端硬碟建好 darknet/bin 目錄。
```python=
!cp ./darknet /content/gdrive/My\ Drive/darknet/bin/darknet
```
成功的話,你在你的雲端硬碟應該會看到有 darknet 這個檔案。

好,到這裡,如果很順利的話,你已經成功一半了。
前面我們已把 darknet 編譯好了,所以再來跑就不用再編譯了,只要把前次的檔案複製回來就好。
```python=
!cp /content/gdrive/My\ Drive/darknet/bin/darknet ./darknet
!chmod +x ./darknet
```
<font color=red>這段僅複製一個檔案到雲端硬碟,並非編譯後的全部內容.在我上面所連結的YOLOv3安裝與實做.ipynb中已經更改了程式碼.</font>
第5步:
定義副程式
imShow/upload/download
然後準備幾個我們等一下會用到呼叫的函數。
* imShow 用來顯示辨識完的圖
* upload 用來上傳要辨識的圖
* download 用來下載辨識完的圖
```python=
def imShow(path):
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
image = cv2.imread(path)
height, width = image.shape[:2]
resized_image = cv2.resize(image,(3*width, 3*height), interpolation = cv2.INTER_CUBIC)
fig = plt.gcf()
fig.set_size_inches(18, 10)
plt.axis("off")
#plt.rcParams['figure.figsize'] = [10, 5]
plt.imshow(cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB))
plt.show()
```
```python=
def upload():
from google.colab import files
uploaded = files.upload()
for name, data in uploaded.items():
with open(name, 'wb') as f:
f.write(data)
print ('saved file', name)
```
```python=
def download(path):
from google.colab import files
files.download(path)
```
第6步:
下載 yolov3.weights
把已訓練好的權重下載過來。
```python=
!wget https://pjreddie.com/media/files/yolov3.weights
```
第7步:
辨識 person.jpg
他的 Data 目錄裡有幾張圖片可以測試,先試看看辨識他自己準備好的圖片 person.jpg。
```python=
!./darknet detect cfg/yolov3.cfg yolov3.weights data/person.jpg -dont-show
imShow('predictions.jpg')
```
我們看到他辨識出3個物體,還有他的機率。
dog: 99%
person: 100%
horse: 100%

第8步:
上傳自己的圖片 mytest.jpg
再來上傳我們自己的圖片。
```python=
upload()
```

第9步:
辨識自己的圖片 mytest.jpg
試看看辨識我們自己的圖片 mytest.jpg。
```python=
!./darknet detect cfg/yolov3.cfg yolov3.weights mytest.jpg -dont-show
imShow('predictions.jpg')
```
我們看到他辨識出4個物體,還有他的機率。
keyboard: 98%
cell phone: 33%
mouse: 100%
cup: 96%

第10步:
下載辨識完的圖片 predictions.jpg
最後你可以把檔案下載回來。
```python=
download("predictions.jpg")
```
以上就是在 Google Colab 用 yolo 辨識圖片的過程啦,有沒有很簡單。
推薦一個視頻
[How we teach computers to understand pictures | Fei Fei Li
](https://youtu.be/40riCqvRoMs)
李飛飛的研究領域主要為電腦視覺、認知神經科學、電腦神經科學和大數據分析。她出版了超過百篇學術論文。視覺網專案(ImageNet)的建立者.
### Part 2 訓練yolov3
接下來回到colab
實做:
訓練YOLO辨識圖片中的人帶口罩的狀態
參考大樹軟體的
[深度學習 如何使用 YOLO 製作即時口罩檢測系統(一) - YOLO簡介](https://www.youtube.com/watch?v=vGhIhitQHBE&t=308s)
[深度學習 如何使用 YOLO 製作即時口罩檢測系統(二) – 建立口罩檢測模型](https://www.youtube.com/watch?v=C0Otd6_jGmE&t=85s)
標記圖片的來源
[kaggle](https://www.kaggle.com/)
簡單說明一下 yolo採用的標記共五個數字所表示的意義:
| Column 1 | Column 2 | Column 3 |Column 4 |Column 5 |
| -------- | -------- | -------- |-------- |-------- |
| 2| 0.459375 |0.375 |0.06375|0.15|
|class編號|歸一化的中心點x座標|歸一化的中心點y座標|歸一化的w|歸一化的h|
class編號:已接下來的口罩訓練為例:0是none;1是poor;2是mask.
train 29148 iterions的狀況
29148: 指示當前訓練的迭代次数
• 0.916980: 是總體的Loss(損失)
• 0.77844 avg: 是平均Loss,這個數值應該越低越好,一般來說,一旦這個數值低於0.060730 avg就可以终止訓練了。
• 0.001000 rate: 代表當前的學習率,是在.cfg文件中定義的。
• 0.878274 seconds: 表示當前批次訓練花費的總時間。
• 1865472 images: 這一行最後的這個數值是29148*32=1865472,表示到目前為止,參與訓練的圖片的總量。
mAP指標:mean average precision,是指每個類别的平均查準率的算術平均值
P指標(查準率):precision的分子是:被預測出且正確的數目;分母是:被預測出的總數目.
舉例來說預測狗:圖中有10個物件,有4個狗6個其他,預測結果框出5個狗,但是其中正確3個,錯了2個.
p=3/5=0.6
順便介紹
召回率recall指標:recall的分子是:被預測出且正確的數目;分母是物件數目.
recall=3/4=0.75
## Part 3 即時影像實作yolov3偵測
這部份不在colab執行.各位練習時應配合自己的電腦環境.
可參考
這篇[深度學習] 如何使用 YOLO 製作即時口罩檢測系統(三) – 建立即時口罩檢測系統
[YouTube](https://www.youtube.com/watch?v=T_zFMRFCFfk&t=432s)
[程式碼](https://github.com/ywchiu/largitdata/blob/master/code/Course_128.ipynb)
最後來到本機,進行即時的影像檢測是否有戴好口罩.
打開終端機,進入 tf2 的虛擬環境,我是在此進行實測的.
source tf2/bin/activate
jupyter notebook
Course_128
<font color=green>心得感言:
機器會學習,這點從前面的簡單口罩檢測已確認.但也無須將機器學習視為萬能,我認為其實正好相反.機器靠著大量的資料學習了判斷是否有戴口罩.這份機器學習到的權重,也僅僅能處理口罩這一件事.其他的可說一概不知.
再以最近常被提到的Google AlphaGo打敗人類「圍棋」王為例.但若讓AlphaGo下「象棋」,它可無法勝任.AlphaGo下棋贏了也不會喜悅,當然輸了也不會沮喪.
要機器學習達到「人」的狀況仍有很長很難的路要走,是否真能達到我是存疑.也就是我認為機器終究只是幫助人的工具.我們更重要該考慮的是機器確實會取代很多人現有的工作,如何在未來仍能具備機器無法取代的能力,自信的生存著.
最後說這些好像有點沈重,還是快樂學習,共同研究程式語言吧!</font>
謝謝大家的參與
真誠感激各位讓我藉由這些報告,持續探討deep learning.能有幸參與此研究團,謝謝大家.
<font color=blue>本次實做了的yolov3的train,仍欠缺重要的test.經過test後才能評估是否達到要求,如此才算是完整的建構出模型.或許下回可以接續報告,如何test此模型的實做.</font>