使用 YOLO World 進行高性能目標檢測
一、介紹
想象一下,家里有一個機器人助手。現(xiàn)在想象一下漫長一天后的混亂——衣服散落各處,玩具到處都是,各種物品都放錯了地方。這個機器人如何識別和整理每一項物品,尤其是如果它以前從未見過這些物品中的一些?傳統(tǒng)的目標檢測器將難以完成這項任務。進入“YOLO World”,這是計算機視覺中一個革命性的新模型,承諾改變機器理解和與周圍環(huán)境的互動方式。
YOLO-World比領先的零樣本目標檢測器快20倍,體積小5倍。
- 傳統(tǒng)目標檢測器(Faster R-CNN、SSD、YOLO)——小而快,但只能檢測其訓練數(shù)據(jù)集中預定義的固定類別中的對象
- 開放詞匯目標檢測(GLIP和Grounding DINO)——靈活但計算密集,需要同時編碼圖像和文本進行預測
根據(jù)論文“YOLO-World: Real-Time Open-Vocabulary Object Detection”(https://arxiv.org/abs/2401.17270),YOLO-World的L版本達到了35.4 AP和52.0 FPS,S版本達到了26.2 AP和74.1 FPS。(在沒有量化或TensorRT的V100上測量)
二、傳統(tǒng)目標檢測器存在的問題
像Faster R-CNN、SSD或原始YOLO這樣的傳統(tǒng)目標檢測器,被構建來識別預定義類別集中的對象。例如,一個在COCO數(shù)據(jù)集上訓練的模型可以檢測多達80種不同的對象。然而,如果你引入一個新項目,例如,一種特定的玩具或一個獨特的瓶子,模型就無法識別它。這種限制可以通過創(chuàng)建新數(shù)據(jù)集、注釋圖像和重新訓練新模型來解決——這是一個耗時且成本高昂的過程。這種僵化阻礙了現(xiàn)實世界應用所需的適應性,其中各種新對象頻繁出現(xiàn)。
1.引入YOLO World
YOLO World以其開放詞匯方法打破了這些限制。將YOLO World想象成一個經(jīng)驗豐富的偵探,不僅擁有已知嫌疑人名單,還具備即時推斷和學習的能力。與前輩不同,YOLO World可以識別它沒有明確訓練過的對象。YOLO World通過結合圖像的視覺線索和文本描述來實現(xiàn)這一點,有效地從上下文和先驗知識中學習。
2..YOLO World如何工作?
YOLO World的學習過程涉及研究充滿圖像和相應描述的大型數(shù)據(jù)集。例如,它可能會分析一張帶有“帶有藍色毯子的床”標題的臥室圖片。它還使用復雜的輔助模塊,如理解描述“橙色條紋貓”的CLIP,以及將圖像特征與這些描述鏈接起來以獲得更深入理解的Reveal Pan。
當你向YOLO World展示一張照片時,它會執(zhí)行基本的目標檢測,識別熟悉的物品,如椅子和桌子。但它更進一步,通過突出不尋?;蛭粗膶ο?,展示其開放詞匯能力。想象一下,看著一個雜亂的房間,不僅僅是看到一個“椅子”或“桌子”,還能識別出“不尋常的玩具”或“稀有瓶子”,即使它以前沒有見過這些特定的對象。
在LVIS上進行零樣本推理的可視化結果。我們采用預訓練的YOLO-World-L,并在COCO val2017上使用LVIS詞匯表(包含1203個類別)進行推理
三、技術細節(jié)和架構
YOLO World的速度和效率的核心是其三個主要組件:
- YOLO檢測器,
- CLIP文本編碼器,
- 用于跨模態(tài)融合的定制網(wǎng)絡。
YOLO檢測器從圖像中提取多尺度特征,而CLIP編碼器將文本描述轉(zhuǎn)換為嵌入。這些嵌入被緩存,使模型能夠在實時中重用它們,而無需重新編碼文本,顯著提高了模型的速度。這種架構與之前的模型如Grounding DINO形成鮮明對比,后者雖然令人印象深刻,但由于嚴重依賴基于變換器的架構,處理圖像的速度要慢得多。YOLO World更輕的基于CNN的主干和提示然后檢測范式使其快20倍,同時保持高準確率。
實際應用和實驗
YOLO World的多功能性在各種實際應用中大放異彩,從幫助例如機器人整理家庭到處理實時視頻流。想象一個機器人助手有效地導航一個雜亂的房間,挑選和分類玩具、書籍和其他物品,全部實時進行,我們還沒有它,所以我們還得再等等。
“遇見可以整理你的房間和分類你的洗衣物的AI機器人”
所以,因為我們沒有機器人或真實的硬件設置,我們將在這一部分在Google Colab上運行我們的實驗,以展示YOLO World通過處理圖像和視頻的能力。
設置涉及安裝庫,例如Roboflow Inference和Supervision,使用簡單的pip install。
# supervision lib to be used for visualization
pip install -q supervision==0.19.0rc3
# inference
pip install -q inference-gpu[yolo-world]==0.9.13
# download some image and video examples
wget -P . -q https://media.roboflow.com/notebooks/examples/dog.jpeg
wget -P . -q https://media.roboflow.com/supervision/cookbooks/yellow-filling.mp4
在這個例子中,一個簡單的腳本展示了模型如何從類別列表中檢測和注釋對象。
import os
import cv2
import supervision as sv
from tqdm import tqdm
from inference.models import YOLOWorld
# model
model = YOLOWorld(model_id="yolo_world/l")
# define classes
classes = ["person", "backpack", "dog", "eye", "nose", "ear", "tongue"]
model.set_classes(classes)
# read image and run model
image = cv2.imread(SOURCE_IMAGE_PATH)
results = model.infer(image)
detections = sv.Detections.from_inference(results)
# draw bbox and show results
BOUNDING_BOX_ANNOTATOR = sv.BoundingBoxAnnotator(thickness=2)
LABEL_ANNOTATOR = sv.LabelAnnotator(text_thickness=2, text_scale=1, text_color=sv.Color.BLACK)
annotated_image = image.copy()
annotated_image = BOUNDING_BOX_ANNOTATOR.annotate(annotated_image, detections)
annotated_image = LABEL_ANNOTATOR.annotate(annotated_image, detections)
sv.plot_image(annotated_image, (10, 10))
調(diào)整置信度水平:
# ...
# same as above
# ...
image = cv2.imread(SOURCE_IMAGE_PATH)
results = model.infer(image, confidence=0.003)
detections = sv.Detections.from_inference(results)
labels = [
f"{classes[class_id]} {confidence:0.3f}"
for class_id, confidence
in zip(detections.class_id, detections.confidence)
]
annotated_image = image.copy()
annotated_image = BOUNDING_BOX_ANNOTATOR.annotate(annotated_image, detections)
annotated_image = LABEL_ANNOTATOR.annotate(annotated_image, detections, labels=labels)
sv.plot_image(annotated_image, (10, 10))
使用非最大抑制(NMS)消除雙重檢測:
# ...
# same as above
# ...
image = cv2.imread(SOURCE_IMAGE_PATH)
results = model.infer(image, confidence=0.003)
detections = sv.Detections.from_inference(results).with_nms(threshold=0.1)
labels = [
f"{classes[class_id]} {confidence:0.3f}"
for class_id, confidence
in zip(detections.class_id, detections.confidence)
]
annotated_image = image.copy()
annotated_image = BOUNDING_BOX_ANNOTATOR.annotate(annotated_image, detections)
annotated_image = LABEL_ANNOTATOR.annotate(annotated_image, detections, labels=labels)
sv.plot_image(annotated_image, (10, 10))
這是從三個不同的腳本獲得的結果:
(左)默認設置(中)使用較低的置信度水平(右)使用較低的置信度水平和非最大抑制
四、視頻處理
# ...
# same part as above + video loading
# ...
generator = sv.get_video_frames_generator(SOURCE_VIDEO_PATH)
frame = next(generator)
sv.plot_image(frame, (10, 10))
# update the classes to be used to detect the objects
classes = ["yellow filling"]
model.set_classes(classes)
results = model.infer(frame, confidence=0.002)
detections = sv.Detections.from_inference(results).with_nms(threshold=0.1)
annotated_image = frame.copy()
annotated_image = BOUNDING_BOX_ANNOTATOR.annotate(annotated_image, detections)
annotated_image = LABEL_ANNOTATOR.annotate(annotated_image, detections)
sv.plot_image(annotated_image, (10, 10))
video_info = sv.VideoInfo.from_video_path(SOURCE_VIDEO_PATH)
print(video_info)
width, height = video_info.resolution_wh
frame_area = width * height
print(frame_area)
results = model.infer(frame, confidence=0.002)
detections = sv.Detections.from_inference(results).with_nms(threshold=0.1)
print(detections.area)
detections = detections[(detections.area / frame_area) < 0.10]
annotated_image = frame.copy()
annotated_image = BOUNDING_BOX_ANNOTATOR.annotate(annotated_image, detections)
annotated_image = LABEL_ANNOTATOR.annotate(annotated_image, detections)
sv.plot_image(annotated_image, (10, 10))
TARGET_VIDEO_PATH = f"{HOME}/yellow-filling-output.mp4"
frame_generator = sv.get_video_frames_generator(SOURCE_VIDEO_PATH)
video_info = sv.VideoInfo.from_video_path(SOURCE_VIDEO_PATH)
width, height = video_info.resolution_wh
frame_area = width * height
frame_area
with sv.VideoSink(target_path=TARGET_VIDEO_PATH, video_info=video_info) as sink:
for frame in tqdm(frame_generator, total=video_info.total_frames):
results = model.infer(frame, confidence=0.002)
detections = sv.Detections.from_inference(results).with_nms(threshold=0.1)
detections = detections[(detections.area / frame_area) < 0.10]
annotated_frame = frame.copy()
annotated_frame = BOUNDING_BOX_ANNOTATOR.annotate(annotated_frame, detections)
annotated_frame = LABEL_ANNOTATOR.annotate(annotated_frame, detections)
sink.write_frame(annotated_frame)
視頻處理的結果:
在Google Colab上,由Google Colab提供的GPU處理單個幀的時間約為65.25毫秒~15Hz
五、挑戰(zhàn)和限制
盡管取得了進步,YOLO World仍然面臨挑戰(zhàn)。該模型雖然比前輩快,但與最先進的實時檢測器相比,仍然存在延遲問題,例如與簡單的YOLOv8相比。
因此,要實現(xiàn)YOLO World的實時處理,這將需要大量的計算資源,使其不太適合硬件能力有限的設置。雖然YOLO World擅長在其學習上下文中識別對象,但它可能會對對象進行錯誤分類或遺漏對象,特別是那些在COCO數(shù)據(jù)集之外的對象。
在精度至關重要且環(huán)境不受控制或高度可變的場景中,訓練有自定義數(shù)據(jù)集的傳統(tǒng)模型可能仍然是首選。
未來的可能性和創(chuàng)新
YOLO World的潛力超出了目標檢測。將其與FastSAM或EfficientSAM等快速分割模型結合起來,可以創(chuàng)建一個比當前組合(如Grounding DINO和SAM)更高效的零樣本分割流程。
這一創(chuàng)新為視頻處理、自動背景移除和動態(tài)對象操作打開了大門。想象一個工廠車間,YOLO World不斷監(jiān)控和編目實時物品,或者一個視頻編輯套件,其中不需要的背景元素被自動移除,這都要歸功于這項技術。
YOLO-World + EfficientSAM — 零樣本分割
六、有效YOLO-World提示的規(guī)則
以下是一套實用的規(guī)則和決策樹,可幫助您在使用YOLO-World時找到最佳提示。
- 調(diào)整置信度水平:(規(guī)則)不要像其他模型那樣依賴高置信度值(>80%)。嘗試非常低的置信度水平(低至0.1%)。(示例)如果預測“吹風機”和“潤膚霜”等對象,變化置信度閾值,并使用低至0.1%至15%。
- 添加空類別:(規(guī)則)包括空類別(非主要興趣的次要對象)以提高檢測準確性。(示例):要檢測車牌并避免對汽車產(chǎn)生誤報,即使不感興趣檢測汽車,也包括“汽車”作為類別。
- 使用兩階段工作流程:(規(guī)則)鏈式模型,第一階段檢測較大的對象,第二階段專注于這些較大對象內(nèi)的較小對象。(示例)首先,檢測人臉,然后裁剪人臉并檢測眼睛。
- 利用顏色:(規(guī)則)當描述性提示失敗時,使用顏色提示。(示例)根據(jù)顏色差異檢測“紅色草莓”與“綠色草莓”。
- 在提示中描述大?。?規(guī)則)在提示中使用大小描述符以提高檢測準確性。(示例)而不是“金屬文件”,使用“小金屬文件”來檢測微小缺陷。
- 后處理改進:(規(guī)則)實施后處理步驟,以過濾掉大組預測或高置信度錯誤。(示例)通過為每個類別設置特定于類別的最大面積閾值來過濾預測。
七、結論
YOLO World代表了目標檢測和人工智能領域的一個重要進步。它學習和適應的能力無需廣泛的重新訓練,使其成為從數(shù)據(jù)注釋、家庭自動化到工業(yè)監(jiān)控等各種應用的強大工具。雖然它有局限性,但其創(chuàng)新方法和未來發(fā)展的潛力使其成為值得探索的技術。YOLO-World可以用于邊緣的零樣本目標檢測,也可以用于自動標記用于訓練微調(diào)模型的圖像。