零基础 从 yolo8 入门计算机视觉超简单:物体识别、图像分类、轨迹追踪、姿势识别
- 安裝 Ultralytics
- 訓(xùn)練
- 模型驗(yàn)證
- 預(yù)測 & 識別
- 導(dǎo)出
- 追蹤
- 圖像分割提取
- 分類
- 姿勢識別
- 軌跡生成
Ultralytics YOLOv8 是備受好評的實(shí)時(shí)目標(biāo)檢測和圖像分割模型,主要功能是物體識別、分割圖片物體、分類、姿態(tài)識別和跟蹤等。Ultralytics 支持使用 CPU、GPU 進(jìn)行訓(xùn)練,支持 x64、arm64 等 CPU 架構(gòu),支持蘋果的 M1/M2 芯片,支持在邊緣設(shè)備中訓(xùn)練和使用。
Ultralytics 對于個(gè)人免費(fèi),使用 【AGPL-3.0 許可】 開源協(xié)議,對于企業(yè)則需要付費(fèi)。
Ultralytics 是框架的名稱,YOLOv8 是該框架默認(rèn)攜帶的模型的版本號,框架默認(rèn)會自帶多種用途模型,我們一般會選擇在官方的模型上做訓(xùn)練。
Ultralytics YOLOv8 的物體識別功能很強(qiáng)大,如下圖所示,能夠準(zhǔn)確識別圖片中化了妝的妹子為 person(人類),甚至把床也識別出來了。
使用 Ultralytics,一般會經(jīng)歷以下過程:
- 訓(xùn)練(Train)模式:在自定義或預(yù)加載的數(shù)據(jù)集上微調(diào)您的模型。
- 驗(yàn)證(Val)模式:訓(xùn)練后進(jìn)行校驗(yàn),以驗(yàn)證模型性能。
- 預(yù)測(Predict)模式:在真實(shí)世界數(shù)據(jù)上釋放模型的預(yù)測能力。
- 導(dǎo)出(Export)模式:以各種格式使模型準(zhǔn)備就緒,部署至生產(chǎn)環(huán)境。
- 跟蹤(Track)模式:將您的目標(biāo)檢測模型擴(kuò)展到實(shí)時(shí)跟蹤應(yīng)用中。
- 基準(zhǔn)(Benchmark)模式:在不同部署環(huán)境中分析模型的速度和準(zhǔn)確性。
所以,本文也會按照該順序,逐步講解。
安裝 Ultralytics
一般來說,直接使用 pip 安裝即可。
# 從PyPI安裝ultralytics包
pip install ultralytics
官方文檔的安裝方式是最詳細(xì)的,其它安裝方式直接參考官方文檔即可。
官方安裝文檔:https://docs.ultralytics.com/zh/quickstart/#ultralytics
安裝 ultralytics 之后,在項(xiàng)目中使用 YOLO 名稱引入 ultralytics:
from ultralytics import YOLO
ultralytics 默認(rèn)是從運(yùn)行目錄中讀寫數(shù)據(jù)集、訓(xùn)練模型的,這樣可能會比較亂。
可以在程序啟動(dòng)時(shí),修改配置運(yùn)行配置:
# 模型和訓(xùn)練模塊,核心
from ultralytics import YOLO
# 設(shè)置模塊
from ultralytics import settings
# 更新設(shè)置
settings.update({'runs_dir': './' , 'tensorboard': False})
settings 也可以導(dǎo)出配置,或者從文件中加載配置:
def load(self):
"""Loads settings from the YAML file."""
super().update(yaml_load(self.file))
def save(self):
"""Saves the current settings to the YAML file."""
yaml_save(self.file, dict(self))
def update(self, *args, **kwargs):
"""Updates a setting value in the current settings."""
super().update(*args, **kwargs)
self.save()
def reset(self):
"""Resets the settings to default and saves them."""
self.clear()
self.update(self.defaults)
self.save()
settings 可以設(shè)置的全部配置如下:
| 名稱 | 示例值 | 數(shù)據(jù)類型 | 描述 |
|---|---|---|---|
settings_version |
'0.0.4' |
str |
Ultralytics settings 版本 |
datasets_dir |
'/path/to/datasets' |
str |
存儲數(shù)據(jù)集的目錄 |
weights_dir |
'/path/to/weights' |
str |
存儲模型權(quán)重的目錄 |
runs_dir |
'/path/to/runs' |
str |
存儲實(shí)驗(yàn)運(yùn)行的目錄 |
uuid |
'a1b2c3d4' |
str |
當(dāng)前設(shè)置的唯一標(biāo)識符 |
sync |
True |
bool |
是否將分析和崩潰同步到HUB |
api_key |
'' |
str |
Ultralytics HUB API Key |
clearml |
True |
bool |
是否使用ClearML記錄 |
comet |
True |
bool |
是否使用Comet ML進(jìn)行實(shí)驗(yàn)跟蹤和可視化 |
dvc |
True |
bool |
是否使用DVC進(jìn)行實(shí)驗(yàn)跟蹤和版本控制 |
hub |
True |
bool |
是否使用Ultralytics HUB集成 |
mlflow |
True |
bool |
是否使用MLFlow進(jìn)行實(shí)驗(yàn)跟蹤 |
neptune |
True |
bool |
是否使用Neptune進(jìn)行實(shí)驗(yàn)跟蹤 |
raytune |
True |
bool |
是否使用Ray Tune進(jìn)行超參數(shù)調(diào)整 |
tensorboard |
True |
bool |
是否使用TensorBoard進(jìn)行可視化 |
wandb |
True |
bool |
是否使用Weights & Biases記錄 |
訓(xùn)練
ultralytics 中常見的文件格式有兩種,模型以 .pt 結(jié)尾,模型或數(shù)據(jù)集以 .yaml 結(jié)尾。
可以基于官方模型進(jìn)行訓(xùn)練,或者從已有模型進(jìn)行訓(xùn)練,甚至在沒有模型的情況下訓(xùn)練出自己的模型。
如果已經(jīng)有模型,則無需再次訓(xùn)練。
官方文檔的 demo 如下:
下面的代碼不能直接啟動(dòng)。
from ultralytics import YOLO
# 加載一個(gè)模型
model = YOLO('yolov8n.yaml') # 從YAML建立一個(gè)新模型
model = YOLO('yolov8n.pt') # 加載預(yù)訓(xùn)練模型(推薦用于訓(xùn)練)
model = YOLO('yolov8n.yaml').load('yolov8n.pt') # 從YAML建立并轉(zhuǎn)移權(quán)重
# 訓(xùn)練模型
results = model.train(data='coco128.yaml', epochs=100, imgsz=640)
官方的 yolov8n.pt 模型和 coco128.yaml 數(shù)據(jù)集,主要是人、動(dòng)物、常見物體,可用于物體識別。
如果選擇使用官方模型,則第一次使用時(shí),會自動(dòng)下載
yolov8n.pt到代碼所在目錄。
我們先來看看 .train() 訓(xùn)練模型時(shí)的參數(shù)。epochs 表示訓(xùn)練多少輪,一般 10 輪即可,100輪需要非常久的!imgsz 表示圖片大小,當(dāng)數(shù)據(jù)集的圖片大小太大時(shí),可以適當(dāng)降低像素,官方的數(shù)據(jù)集圖片大小是 640*480 ,已經(jīng)提前處理好大小了。
coco128.yaml 是官方提供的數(shù)據(jù)集合,有 128 張圖片,在程序首次運(yùn)行時(shí),會自動(dòng)從官方倉庫中拉取數(shù)據(jù)集存儲到 datasets/coco128 下面,其中里面包含了一些圖片和標(biāo)注。當(dāng)然,我們也可以從開源社區(qū)中獲取更多的數(shù)據(jù)集,以及自己制作數(shù)據(jù)集,用來訓(xùn)練模型。
然后再回到加載模型這里。
我們通過官方配置文件,從零訓(xùn)練出一個(gè)模型:
from ultralytics import YOLO
# 加載一個(gè)模型
model = YOLO('yolov8n.yaml') # 從YAML建立一個(gè)新模型
# 訓(xùn)練模型
results = model.train(data='coco128.yaml', epochs=10, imgsz=640)
由于筆者只有 AMD 5600G,是集成顯卡,因此跑起來特別慢。
如果你有指定的多個(gè),可以在訓(xùn)練時(shí)指定:
results = model.train(data='coco128.yaml', epochs=10, imgsz=640, device=0)如果不指定,框架會自動(dòng)選擇 GPU。
可能筆者是 AMD 的 CPU,也有可能是因?yàn)椴恢С旨娠@卡,所以筆者是使用 CPU 訓(xùn)練的,超級慢。
訓(xùn)練出的模型會存儲在 detect 目錄下。其它兩種方式訓(xùn)練的模型也是如此,都會在 detect 目錄下。
我們也可以導(dǎo)入已有的模型:
# 加載官方預(yù)訓(xùn)練模型
# model = YOLO('yolov8n.pt')
# 訓(xùn)練過的模型
model = YOLO('detect/train/weights/best.pt')
在使用 .train() 訓(xùn)練模型時(shí),可以傳遞很多參數(shù),全部參數(shù)說明如下:
| 鍵 | 值 | 描述 |
|---|---|---|
model |
None |
模型文件路徑,例如 yolov8n.pt, yolov8n.yaml |
data |
None |
數(shù)據(jù)文件路徑,例如 coco128.yaml |
epochs |
100 |
訓(xùn)練的輪次數(shù)量 |
patience |
50 |
早停訓(xùn)練的等待輪次 |
batch |
16 |
每批圖像數(shù)量(-1為自動(dòng)批大小) |
imgsz |
640 |
輸入圖像的大小,以整數(shù)表示 |
save |
True |
保存訓(xùn)練檢查點(diǎn)和預(yù)測結(jié)果 |
save_period |
-1 |
每x輪次保存檢查點(diǎn)(如果<1則禁用) |
cache |
False |
True/ram, disk 或 False。使用緩存加載數(shù)據(jù) |
device |
None |
運(yùn)行設(shè)備,例如 cuda device=0 或 device=0,1,2,3 或 device=cpu |
workers |
8 |
數(shù)據(jù)加載的工作線程數(shù)(如果DDP則為每個(gè)RANK) |
project |
None |
項(xiàng)目名稱 |
name |
None |
實(shí)驗(yàn)名稱 |
exist_ok |
False |
是否覆蓋現(xiàn)有實(shí)驗(yàn) |
pretrained |
True |
(bool 或 str) 是否使用預(yù)訓(xùn)練模型(bool)或從中加載權(quán)重的模型(str) |
optimizer |
'auto' |
使用的優(yōu)化器,選擇范圍=[SGD, Adam, Adamax, AdamW, NAdam, RAdam, RMSProp, auto] |
verbose |
False |
是否打印詳細(xì)輸出 |
seed |
0 |
隨機(jī)種子,用于可重復(fù)性 |
deterministic |
True |
是否啟用確定性模式 |
single_cls |
False |
將多類數(shù)據(jù)作為單類訓(xùn)練 |
rect |
False |
矩形訓(xùn)練,每批為最小填充整合 |
cos_lr |
False |
使用余弦學(xué)習(xí)率調(diào)度器 |
close_mosaic |
10 |
(int) 最后輪次禁用馬賽克增強(qiáng)(0為禁用) |
resume |
False |
從最后檢查點(diǎn)恢復(fù)訓(xùn)練 |
amp |
True |
自動(dòng)混合精度(AMP)訓(xùn)練,選擇范圍=[True, False] |
fraction |
1.0 |
訓(xùn)練的數(shù)據(jù)集比例(默認(rèn)為1.0,即訓(xùn)練集中的所有圖像) |
profile |
False |
在訓(xùn)練期間為記錄器分析ONNX和TensorRT速度 |
freeze |
None |
(int 或 list, 可選) 在訓(xùn)練期間凍結(jié)前n層,或凍結(jié)層索引列表 |
lr0 |
0.01 |
初始學(xué)習(xí)率(例如 SGD=1E-2, Adam=1E-3) |
lrf |
0.01 |
最終學(xué)習(xí)率 (lr0 * lrf) |
momentum |
0.937 |
SGD動(dòng)量/Adam beta1 |
weight_decay |
0.0005 |
優(yōu)化器權(quán)重衰減5e-4 |
warmup_epochs |
3.0 |
熱身輪次(小數(shù)ok) |
warmup_momentum |
0.8 |
熱身初始動(dòng)量 |
warmup_bias_lr |
0.1 |
熱身初始偏差lr |
box |
7.5 |
框損失增益 |
cls |
0.5 |
cls損失增益(根據(jù)像素縮放) |
dfl |
1.5 |
dfl損失增益 |
pose |
12.0 |
姿態(tài)損失增益(僅限姿態(tài)) |
kobj |
2.0 |
關(guān)鍵點(diǎn)obj損失增益(僅限姿態(tài)) |
label_smoothing |
0.0 |
標(biāo)簽平滑(小數(shù)) |
nbs |
64 |
標(biāo)稱批大小 |
overlap_mask |
True |
訓(xùn)練期間掩碼應(yīng)重疊(僅限分割訓(xùn)練) |
mask_ratio |
4 |
掩碼降采樣比率(僅限分割訓(xùn)練) |
dropout |
0.0 |
使用dropout正則化(僅限分類訓(xùn)練) |
val |
True |
訓(xùn)練期間驗(yàn)證/測試 |
模型驗(yàn)證
前一小節(jié)中,我們使用了官方帶有 128 張圖片的 coco128.yaml 數(shù)據(jù)集進(jìn)行訓(xùn)練,訓(xùn)練完成后,需要進(jìn)行模型驗(yàn)證,以便在 coco128.yaml 數(shù)據(jù)集上驗(yàn)證訓(xùn)練過的模型的準(zhǔn)確性。
此外,數(shù)據(jù)集也分為多種:
- 訓(xùn)練集(Training Set):用于訓(xùn)練和調(diào)整模型參數(shù)。
- 驗(yàn)證集(Validation Set):用于驗(yàn)證模型精度和調(diào)整模型參數(shù)。
- 測試集(Test Set):用于驗(yàn)證模型的泛化能力。
對于模型驗(yàn)證這一部分,官方文檔的描述不多,同時(shí)本文作為入門文章,不會深入講解這些細(xì)節(jié),所以我們只需要記得自行訓(xùn)練的模型,都加上模型驗(yàn)證的代碼模板即可。
在已經(jīng)訓(xùn)練的模型中驗(yàn)證的模板如下:
from ultralytics import YOLO
# 加載訓(xùn)練后的模型
model = YOLO('detect/train3/weights/best.pt')
# 驗(yàn)證模型
metrics = model.val() # 無需參數(shù),數(shù)據(jù)集和設(shè)置記憶
metrics.box.map # map50-95
metrics.box.map50 # map50
metrics.box.map75 # map75
metrics.box.maps # 包含每個(gè)類別的map50-95列表
一般,在訓(xùn)練之后立即驗(yàn)證:
from ultralytics import YOLO
model = YOLO('yolov8n.pt') # 加載預(yù)訓(xùn)練模型(推薦用于訓(xùn)練)
# 訓(xùn)練模型
results = model.train(data='coco128.yaml', epochs=10, imgsz=640)
# 驗(yàn)證模型
metrics = model.val() # 無需參數(shù),數(shù)據(jù)集和設(shè)置記憶
metrics.box.map # map50-95
metrics.box.map50 # map50
metrics.box.map75 # map75
metrics.box.maps # 包含每個(gè)類別的map50-95列表
驗(yàn)證結(jié)果:
前面提到過,coco128.yaml 數(shù)據(jù)集主要是人、動(dòng)物和常見物體的圖片,因此控制臺列出了每種標(biāo)記(person 人類、car 汽車等) 的識別驗(yàn)證結(jié)果。
當(dāng)然,我們是入門階段,這些信息對我們作用不大。
預(yù)測 & 識別
來到了激動(dòng)人心的階段,我們可以使用現(xiàn)有的模型或官方模型對圖片進(jìn)行識別。
你可以將下面兩張圖片下載保存:
下面兩張圖片,是代碼識別后的結(jié)果,會自動(dòng)將圖片中識別到的物體標(biāo)記名稱以及使用矩形框選出來。
from ultralytics import YOLO
from PIL import Image
# 加載訓(xùn)練后的模型
model = YOLO('detect/train3/weights/best.pt')
# 導(dǎo)入并識別圖片,results 是處理后的結(jié)果
results = model(['img1.jpg', 'img2.jpg'])
# 保存處理后的圖片到目錄中
i = 0
for r in results:
i += 1
im_array = r.plot() # 繪制包含預(yù)測結(jié)果的BGR numpy數(shù)組
im = Image.fromarray(im_array[..., ::-1]) # RGB PIL圖像
im.save('results/' + str(i) + '.jpg') # 保存圖像
當(dāng)然,我們也可以在處理圖片之前預(yù)覽圖片:
im.show() # 彈出窗口,預(yù)覽圖像
im.save('results/' + str(i) + '.jpg') # 保存圖像
如果只需要獲取識別信息,不需要處理圖片,那么可以這樣打印信息:
from ultralytics import YOLO
from PIL import Image
# 加載訓(xùn)練后的模型
model = YOLO('detect/train3/weights/best.pt')
# 導(dǎo)入并識別圖片,results 是處理后的結(jié)果
results = model(['img1.jpg', 'img2.jpg'])
# 處理結(jié)果列表
for result in results:
boxes = result.boxes # 邊界框輸出的 Boxes 對象
masks = result.masks # 分割掩碼輸出的 Masks 對象
keypoints = result.keypoints # 姿態(tài)輸出的 Keypoints 對象
probs = result.probs # 分類輸出的 Probs 對象
print("圖片邊框")
print(boxes)
print("分割掩碼")
print(masks)
print("姿勢輸出")
print(keypoints)
print("分類輸出")
print(probs)
注意,上面的結(jié)果除了邊框有值,其它都是 None,因?yàn)槲覀冎蛔R別圖片,并沒有做分類、切割、姿勢識別等。
前面提到,results 是處理之后的結(jié)果,results 是一個(gè) Results 對象,Results 對象具有的屬性如下:
| 屬性 | 類型 | 描述 |
|---|---|---|
orig_img |
numpy.ndarray |
原始圖像的numpy數(shù)組。 |
orig_shape |
tuple |
原始圖像的形狀,格式為(高度,寬度)。 |
boxes |
Boxes, 可選 |
包含檢測邊界框的Boxes對象。 |
masks |
Masks, 可選 |
包含檢測掩碼的Masks對象。 |
probs |
Probs, 可選 |
包含每個(gè)類別的概率的Probs對象,用于分類任務(wù)。 |
keypoints |
Keypoints, 可選 |
包含每個(gè)對象檢測到的關(guān)鍵點(diǎn)的Keypoints對象。 |
speed |
dict |
以毫秒為單位的每張圖片的預(yù)處理、推理和后處理速度的字典。 |
names |
dict |
類別名稱的字典。 |
path |
str |
圖像文件的路徑。 |
Results具有以下方法:
| 方法 | 返回類型 | 描述 |
|---|---|---|
__getitem__() |
Results |
返回指定索引的Results對象。 |
__len__() |
int |
返回Results對象中的檢測數(shù)量。 |
update() |
None |
更新Results對象的boxes, masks和probs屬性。 |
cpu() |
Results |
將所有張量移動(dòng)到CPU內(nèi)存上的Results對象的副本。 |
numpy() |
Results |
將所有張量轉(zhuǎn)換為numpy數(shù)組的Results對象的副本。 |
cuda() |
Results |
將所有張量移動(dòng)到GPU內(nèi)存上的Results對象的副本。 |
to() |
Results |
返回將張量移動(dòng)到指定設(shè)備和dtype的Results對象的副本。 |
new() |
Results |
返回一個(gè)帶有相同圖像、路徑和名稱的新Results對象。 |
keys() |
List[str] |
返回非空屬性名稱的列表。 |
plot() |
numpy.ndarray |
繪制檢測結(jié)果。返回帶有注釋的圖像的numpy數(shù)組。 |
verbose() |
str |
返回每個(gè)任務(wù)的日志字符串。 |
save_txt() |
None |
將預(yù)測保存到txt文件中。 |
save_crop() |
None |
將裁剪的預(yù)測保存到save_dir/cls/file_name.jpg。 |
tojson() |
None |
將對象轉(zhuǎn)換為JSON格式。 |
除了本地圖片外,ultralytics 還支持視頻流,可以從本地或網(wǎng)絡(luò)中導(dǎo)入要識別的資源。對于視頻流的處理,本文的后續(xù)章節(jié)再介紹。
ultralytics 支持識別的其它資源:
| 來源 | 參數(shù) | 類型 | 備注 |
|---|---|---|---|
| image | 'image.jpg' |
str 或 Path
|
單個(gè)圖像文件。 |
| URL | 'https://ultralytics.com/images/bus.jpg' |
str |
圖像的 URL 地址。 |
| screenshot | 'screen' |
str |
截取屏幕圖像。 |
| PIL | Image.open('im.jpg') |
PIL.Image |
RGB 通道的 HWC 格式圖像。 |
| OpenCV | cv2.imread('im.jpg') |
np.ndarray |
BGR 通道的 HWC 格式圖像 uint8 (0-255)。 |
| numpy | np.zeros((640,1280,3)) |
np.ndarray |
BGR 通道的 HWC 格式圖像 uint8 (0-255)。 |
| torch | torch.zeros(16,3,320,640) |
torch.Tensor |
RGB 通道的 BCHW 格式圖像 float32 (0.0-1.0)。 |
| CSV | 'sources.csv' |
str 或 Path
|
包含圖像、視頻或目錄路徑的 CSV 文件。 |
| video? | 'video.mp4' |
str 或 Path
|
如 MP4, AVI 等格式的視頻文件。 |
| directory? | 'path/' |
str 或 Path
|
包含圖像或視頻文件的目錄路徑。 |
| glob ? | 'path/*.jpg' |
str |
匹配多個(gè)文件的通配符模式。使用 * 字符作為通配符。 |
| YouTube ? | 'https://youtu.be/LNwODJXcvt4' |
str |
YouTube 視頻的 URL 地址。 |
| stream ? | 'rtsp://example.com/media.mp4' |
str |
RTSP, RTMP, TCP 或 IP 地址等流協(xié)議的 URL 地址。 |
| multi-stream? | 'list.streams' |
str 或 Path
|
一個(gè)流 URL 每行的 *.streams 文本文件,例如 8 個(gè)流將以 8 的批處理大小運(yùn)行。 |
如果要了解每種資源的導(dǎo)入方式,可以打開 https://docs.ultralytics.com/zh/modes/predict/#_4
本文不再贅述所有導(dǎo)入方式,不過本文后續(xù)會介紹視頻流等資源識別。
導(dǎo)出
ultralytics 支持將訓(xùn)練后的模型導(dǎo)出為 ONNX、 TensorRT、 CoreML 等格式,然后我們可以使用其它框架或其它語言進(jìn)行調(diào)用,例如 C# 的 ML.NET 框架。
from ultralytics import YOLO
# 加載模型 .pt 文件模型
model = YOLO('path/to/best.pt')
# 導(dǎo)出為其它類型的模型
model.export(format='onnx')
導(dǎo)出為其它模型時(shí),需要安裝對應(yīng)支持包,如果本地沒有安裝過,則第一次會自動(dòng)安裝。
代碼執(zhí)行后,控制臺會打印出模型文件被導(dǎo)出到哪個(gè)位置:
ultralytics 支持將模型導(dǎo)出為以下格式:
| 格式 |
format 參數(shù) |
模型 | 元數(shù)據(jù) | 參數(shù) |
|---|---|---|---|---|
| PyTorch | - | yolov8n.pt |
? | - |
| TorchScript | torchscript |
yolov8n.torchscript |
? |
imgsz, optimize
|
| ONNX | onnx |
yolov8n.onnx |
? |
imgsz, half, dynamic, simplify, opset
|
| OpenVINO | openvino |
yolov8n_openvino_model/ |
? |
imgsz, half
|
| TensorRT | engine |
yolov8n.engine |
? |
imgsz, half, dynamic, simplify, workspace
|
| CoreML | coreml |
yolov8n.mlpackage |
? |
imgsz, half, int8, nms
|
| TF SavedModel | saved_model |
yolov8n_saved_model/ |
? |
imgsz, keras
|
| TF GraphDef | pb |
yolov8n.pb |
? | imgsz |
| TF Lite | tflite |
yolov8n.tflite |
? |
imgsz, half, int8
|
| TF Edge TPU | edgetpu |
yolov8n_edgetpu.tflite |
? | imgsz |
| TF.js | tfjs |
yolov8n_web_model/ |
? | imgsz |
| PaddlePaddle | paddle |
yolov8n_paddle_model/ |
? | imgsz |
| ncnn | ncnn |
yolov8n_ncnn_model/ |
? |
imgsz, half
|
追蹤
Ultralytics 的追蹤可以處理視頻中的物體。前面筆者已經(jīng)介紹了通過圖片進(jìn)行物體識別,其實(shí)還支持對圖片進(jìn)行姿勢識別、圖片分類、將物體從圖片中切割出來,這些等后面的章節(jié)再介紹。Ultralytics 的追蹤也支持物體識別、姿勢識別等,在本節(jié)中,筆者將介紹如何在視頻中識別和追蹤物體,在后面的章節(jié)中會介紹更多的示例。
Ultralytics YOLO 擴(kuò)展了其物體檢測功能,以提供強(qiáng)大且多功能的物體追蹤:
- 實(shí)時(shí)追蹤: 在高幀率視頻中無縫追蹤物體。
- 支持多個(gè)追蹤器: 從多種成熟的追蹤算法中選擇。
- 自定義追蹤器配置: 通過調(diào)整各種參數(shù)來定制追蹤算法,以滿足特定需求。
Ultralytics 默認(rèn)有兩種追蹤器。
- BoT-SORT - 模型文件為
botsort.yaml,默認(rèn)使用,不需要配置。 - ByteTrack - 模型文件為
bytetrack.yaml。
以下代碼演示了使用 cv2 加載視頻文件,并逐幀識別圖片中的物體,然后每識別一幀,就顯示到桌面中。
from ultralytics import YOLO
import cv2
# 加載自己訓(xùn)練的物體識別模型
model = YOLO('detect/train3/weights/best.pt')
# 或者使用官方訓(xùn)練的物體識別模型
# model = YOLO('yolov8n.pt')
# 使用 cv2 加載視頻文件
video_path = "1.mp4"
cap = cv2.VideoCapture(video_path)
# 循環(huán)遍歷視頻幀
while cap.isOpened():
# 從視頻讀取一幀
success, frame = cap.read()
if success:
# 在幀上運(yùn)行YOLOv8追蹤,持續(xù)追蹤幀間的物體
results = model.track(frame, persist=True)
# 在幀上展示結(jié)果
annotated_frame = results[0].plot()
# 使用 cv2 彈出窗口,并展示帶注釋的幀
# 也就是一邊識別,一邊播放視頻
cv2.imshow("YOLOv8 Tracking", annotated_frame)
# 如果按下'q'則退出循環(huán)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
# 如果視頻結(jié)束則退出循環(huán)
break
# 釋放視頻捕獲對象并關(guān)閉顯示窗口
cap.release()
cv2.destroyAllWindows()
當(dāng)然,由于筆者下載的視頻比較模糊,以及訓(xùn)練的數(shù)據(jù)集不大,識別出來的物體名稱不是很理想,不過其追蹤器確實(shí)確實(shí)牛批。
圖像分割提取
圖像分割用于在識別圖片中的物體后,將物體從圖片中提取出來。
示例代碼如下:
from ultralytics import YOLO
# 加載 yolov8n-seg 模型
model = YOLO('yolov8n-seg.pt')
# 訓(xùn)練模型
# results = model.train(data='coco128-seg.yaml', epochs=100, imgsz=640)
# 驗(yàn)證
# ... ...
# 對圖像進(jìn)行處理
results = model(['img1.jpg', 'img2.jpg'])
# 保存處理后的圖片到目錄中
i = 0
for r in results:
i += 1
im_array = r.save_crop(save_dir="results")
提取到的物體圖片會被存儲到:
如果不需要提取物體,由于 ultralytics 會先創(chuàng)建圖片蒙版,因此我們可以導(dǎo)出帶有物體蒙版的圖片。
from ultralytics import YOLO
from PIL import Image
# 加載 yolov8n-seg 模型
model = YOLO('yolov8n-seg.pt')
# 訓(xùn)練模型
# results = model.train(data='coco128-seg.yaml', epochs=100, imgsz=640)
# 驗(yàn)證
# ... ...
# 對圖像進(jìn)行處理
results = model(['img1.jpg', 'img2.jpg'])
# 保存處理后的圖片到目錄中
i = 0
for r in results:
i += 1
im_array = r.plot() # 繪制包含預(yù)測結(jié)果的BGR numpy數(shù)組
im = Image.fromarray(im_array[..., ::-1]) # RGB PIL圖像
im.save('results/' + str(i) + '.jpg') # 保存圖像
分類
很明顯,用于分類圖片。
分類圖片需要使用官方的 yolov8n-cls.pt 模型。
官方提供了一個(gè) mnist160 數(shù)據(jù)集,該數(shù)據(jù)集是從 0-9 的手寫圖片,因此我們訓(xùn)練模型之后,也是用來做手寫數(shù)字識別的。
這里隨便寫三個(gè)數(shù)字:
由于數(shù)據(jù)量不大,因此我們可以直接訓(xùn)練然后使用訓(xùn)練后的模型提取圖片中的文字:
from ultralytics import YOLO
# 加載 yolov8n-cls 模型
model = YOLO('yolov8n-cls.pt')
# 訓(xùn)練模型
results = model.train(data='mnist160', epochs=100, imgsz=64)
# 驗(yàn)證
# ... ...
# 對圖像進(jìn)行處理
results = model(['666.png'])
# 保存處理后的圖片到目錄中
i = 0
for r in results:
r.save_txt(txt_file="results/cls"+ str(i) + '.txt')
i += 1
因?yàn)橛?xùn)練的數(shù)據(jù)集是單數(shù)字的,因此對多數(shù)字的支持有點(diǎn)問題。
改成大大的 6 ,再次識別:
姿勢識別
姿勢識別用于在圖片或視頻中給人體進(jìn)行打點(diǎn)、劃線,然后追蹤人體的姿勢變化。
示例代碼如下:
import cv2
from ultralytics import YOLO
# 加載 yolov8n-pose 模型,并進(jìn)行訓(xùn)練
model = YOLO('yolov8n-pose.pt')
results = model.train(data='coco8-pose.yaml', epochs=10, imgsz=640)
# 打開視頻文件
video_path = "1.mp4"
cap = cv2.VideoCapture(video_path)
# 循環(huán)遍歷視頻幀
while cap.isOpened():
# 從視頻讀取一幀
success, frame = cap.read()
if success:
# 在幀上運(yùn)行YOLOv8追蹤,持續(xù)追蹤幀間的物體
results = model.track(frame, persist=True)
# 在幀上展示結(jié)果
annotated_frame = results[0].plot()
# 展示帶注釋的幀
cv2.imshow("YOLOv8 Tracking", annotated_frame)
# 如果按下'q'則退出循環(huán)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
# 如果視頻結(jié)束則退出循環(huán)
break
# 釋放視頻捕獲對象并關(guān)閉顯示窗口
cap.release()
cv2.destroyAllWindows()
軌跡生成
在視頻中識別追蹤物體時(shí),還可以對物體的運(yùn)行軌跡進(jìn)行追蹤。
手頭上沒有更多視頻演示,將就一下。
示例代碼如下:
from collections import defaultdict
import cv2
import numpy as np
from ultralytics import YOLO
# 加載 yolov8n.pt 模型,也可以使用其它模型
model = YOLO('yolov8n.pt')
# 打開視頻
video_path = "0.mp4"
cap = cv2.VideoCapture(video_path)
# 保存歷史記錄
track_history = defaultdict(lambda: [])
# 處理視頻的每一幀
while cap.isOpened():
success, frame = cap.read()
if success:
# 追蹤
results = model.track(frame, persist=True)
# 讀取當(dāng)前幀中物體的框
boxes = results[0].boxes.xywh.cpu()
# 如果未識別到圖像有框時(shí),則忽略
if results[0].boxes.id is None:
continue
# 獲取每個(gè)被追蹤的物體 id
track_ids = results[0].boxes.id.int().cpu().tolist()
annotated_frame = results[0].plot()
# 繪制
for box, track_id in zip(boxes, track_ids):
x, y, w, h = box
track = track_history[track_id]
track.append((float(x), float(y)))
if len(track) > 30:
track.pop(0)
points = np.hstack(track).astype(np.int32).reshape((-1, 1, 2))
cv2.polylines(annotated_frame, [points], isClosed=False, color=(230, 230, 230), thickness=10)
cv2.imshow("YOLOv8 Tracking", annotated_frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
else:
break
cap.release()
cv2.destroyAllWindows()
總結(jié)
以上是生活随笔為你收集整理的零基础 从 yolo8 入门计算机视觉超简单:物体识别、图像分类、轨迹追踪、姿势识别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 不妄
- 下一篇: C++ Qt开发:Slider滑块条组件