YOLO 一開始其實只是一篇論文,v2, v3….又是進化的論文。要詳細了解每一篇的論文,絕對要花很多時間研讀,更何況到目前為止共有 8 篇。
v1 : 2015年 Joseph Redmon/Ali Farhadi
v2 : 2016/12/25
v3 : 2018/04/08 : Joseph 退出
v4 : 2020 04/23 台灣、俄羅斯 : darknet
v5 : 2020/05/18 Glenn Jocher/ultralytics/Pytorch :
v6 : 20220623 : 美國
v7 : 2022/07/12 : 台灣
v8 : 2023/01/10 ultralytics
原由
1991 年魔鬼終結者 2 這部電影出現很多驚人的橋段,如下圖所示。
一部 “機器” 竟然能判斷這個是 “人類”,甚至還能丈量尺寸大小。這畫面對當時的人非常震憾,也覺得這個導演是個天才。
丈量尺寸的方法,是有紅外線等方式精準測量。但判讀 “人類” 這件事經過 30 年的研發,才發展出可以 “大約” 辨識 “人類” 的演算法。
附帶提一件事,本人也因為這部電影,在 30 年前開始走入 Linux 世界。
安裝
v8 版直接由 pip 安裝 ultralytics 套件即可,不用像 v7 版還要手動下載 github 原始碼那麼麻煩。
但是 ultralytics 會自動安裝無法使用 cuda 的 Pytorch,所以請先安裝可用 cuda 的 Pytorch,然後才安裝 ultralytics。
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 --no-cache-dir
pip install ultralytics
偵測
直接在 Terminal 執行如下指令,此指令會自動下載 “yolov8n.pt” 權重,偵測的結果放置在 ./run/detect/predict目錄下。
yolo predict model=yolov8n.pt source="https://ultralytics.com/images/bus.jpg"
其它權重下載
上述的 yolov8n.pt 又稱為預訓練權重(pretrain),由官網使用 coco 資料集所訓練出來的權重。除了可以用來偵測 80 種物件外,也可以用來訓練其它資料集的權重,可以到如下網址下載。
https://github.com/ultralytics/ultralytics 網站往下拉就有預訓練權重可供下載。預訓練權重有 yolov8n、yolov8s、yolov8m、yolov8l、yolov8x 共 5 種,愈往下愈精準但速度愈慢。請將下載的 .pt 檔儲存在專案目錄下。
使用程式碼偵測
import YOLO 產生 model 模型,然用 model.predict() 即可偵測,傳入裏面的參數,可以是圖片檔名,也可以是讀入記憶体的 cv2 格式。
results[0].boxes.cls 是偵測到的物件索引編號,為 torch 格式。results[0].boxes.xyxy 則是所有物件方框的座標。
import platform import cv2 import numpy as np from PIL import Image, ImageFont, ImageDraw from ultralytics import YOLO import pylab as plt def text(img, text, xy=(0, 0), color=(0, 0, 0), size=12): pil = Image.fromarray(img) s = platform.system() if s == "Linux": font =ImageFont.truetype('/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc', size) elif s == "Darwin": font = ImageFont.truetype('....', size) else: font = ImageFont.truetype('simsun.ttc', size) ImageDraw.Draw(pil).text(xy, text, font=font, fill=color) return np.array(pil) model=YOLO('yolov8x.pt') img=cv2.imdecode(np.fromfile("street.jpg", dtype=np.uint8), cv2.IMREAD_UNCHANGED) img=img[:,:,::-1].copy()#一定要 copy,否則無法畫框線 #results=model.predict("street.jpg") results=model.predict(img) print('物件種類 : ',results[0].boxes.cls)#cls : class print('座標 : ',results[0].boxes.xyxy) #print(results[0].names)#列出80種物件的索引及名稱 # for i in results[0].boxes.cls: # idx=int(i.cpu().numpy()) # print(idx, results[0].names[idx]) names=[results[0].names[int(i.cpu().numpy())] for i in results[0].boxes.cls] boxes=results[0].boxes.xyxy for box, name in zip(boxes, names): box=box.cpu().numpy() print(name, box) x1 = int(box[0]) y1 = int(box[1]) x2 = int(box[2]) y2 = int(box[3]) img=cv2.rectangle(img, (x1, y1), (x2, y2), (0,255,0), 1) img=text(img, name, (x1, y1-20), color=(0,0,255), size=16) plt.imshow(img) plt.show()