技術(shù)文章:Yolov3 CPU推理性能比較-Onnx、OpenCV、Darknet
為實(shí)時(shí)目標(biāo)檢測(cè)應(yīng)用程序選擇正確的推理框架變得非常具有挑戰(zhàn)性,尤其是當(dāng)模型應(yīng)該在低功耗設(shè)備上運(yùn)行時(shí)。在本文中,你將了解如何根據(jù)你的需要選擇最佳的推理檢測(cè)器,并發(fā)現(xiàn)它可以給你帶來(lái)巨大的性能提升。通常,當(dāng)我們將模型部署到CPU或移動(dòng)設(shè)備上時(shí),往往只關(guān)注于輕量級(jí)的模型體系結(jié)構(gòu),而忽略了對(duì)快速推理機(jī)的研究。在研究CPU設(shè)備上的快速推理時(shí),我測(cè)試了提供穩(wěn)定python API的各種框架。今天將重點(diǎn)介紹Onnxruntime、opencvdnn和Darknet框架,并從性能(運(yùn)行時(shí)間)和準(zhǔn)確性方面對(duì)它們進(jìn)行度量。
Onnxruntime
opencvdnn
Darknet
我們將使用兩種常見的目標(biāo)檢測(cè)模型進(jìn)行性能測(cè)量:Yolov3架構(gòu):image_size = 480*480
classes = 98
BFLOPS =87.892
Tiny-Yolov3_3layers 體系結(jié)構(gòu):image_size= 1024*1024
classes =98
BFLOPS= 46.448
這兩個(gè)模型都是使用AlexeyAB的Darknet框架對(duì)自定義數(shù)據(jù)進(jìn)行訓(xùn)練的。現(xiàn)在,讓我們用我們要測(cè)試的探測(cè)器來(lái)運(yùn)行推理。Darknet探測(cè)器Darknet是訓(xùn)練 YOLO 目標(biāo)檢測(cè)模型的官方框架。此外,它還提供了對(duì)*.weights文件格式的模型進(jìn)行推理的能力,該文件格式與訓(xùn)練輸出的格式相同。推理有兩種方法:不同數(shù)量的圖像:darknet detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights -thresh 0.25
一個(gè)圖像darknet detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights dog.png
OpenCV DNN探測(cè)器Opencv-DNN是計(jì)算機(jī)視覺領(lǐng)域常用的Opencv庫(kù)的擴(kuò)展。Darknet聲稱OpenCV-DNN是“CPU設(shè)備上YOLV4/V3最快的推理實(shí)現(xiàn)”,因?yàn)樗咝У腃&C++實(shí)現(xiàn)。由于其方便的Python API,直接將darknet權(quán)重加載到opencv-dnn即可。這是E2E推理的代碼片段:import cv2
import numpy as np
# 指定模型的網(wǎng)絡(luò)大小
network_size = (480,480)
# Darknet cfg文件路徑
cfg_path = 'yolov3.cfg'
# Darknet 權(quán)重路徑
weights_path = 'yolov3.weights'
# 定義推理引擎
net = cv2.dnn.readNetFromDarknet(cfg_path, weights_path)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
_layer_names = net.getLayerNames()
_output_layers = [_layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
# 讀取圖像作為輸入
img_path = 'dog.png'
img = cv2.imread(img_path)
image_blob = cv2.dnn.blobFromImage(img, 1 / 255.0, network_size, swapRB=True, crop=False)
net.setInput(image_blob, "data")
# 運(yùn)行推理
layers_result = net.forward(_output_layers)
# 將layers_result轉(zhuǎn)換為bbox,conf和類
def get_final_predictions(outputs, img, threshold, nms_threshold):
height, width = img.shape[0], img.shape[1]
boxes, confs, class_ids = [], [], []
for output in outputs:
for detect in output:
scores = detect[5:]
class_id = np.a(chǎn)rgmax(scores)
conf = scores[class_id]
if conf > threshold:
center_x = int(detect[0] * width)
center_y = int(detect[1] * height)
w = int(detect[2] * width)
h = int(detect[3] * height)
x = int(center_x - w/2)
y = int(center_y - h / 2)
boxes.a(chǎn)ppend([x, y, w, h])
confs.a(chǎn)ppend(float(conf))
class_ids.a(chǎn)ppend(class_id)
merge_boxes_ids = cv2.dnn.NMSBoxes(boxes, confs, threshold, nms_threshold)
# 僅過(guò)濾nms之后剩余的框
boxes = [boxes[int(i)] for i in merge_boxes_ids]
confs = [confs[int(i)] for i in merge_boxes_ids]
class_ids = [class_ids[int(i)] for i in merge_boxes_ids]
return boxes, confs, class_ids
boxes, confs, class_ids = get_final_predictions(layers_result, img, 0.3, 0.3)
Onnxruntime檢測(cè)器Onnxruntime是由微軟維護(hù)的,由于其內(nèi)置的優(yōu)化和獨(dú)特的ONNX權(quán)重格式文件,它聲稱可以顯著加快推理速度。正如你在下一張圖片中看到的,它支持各種風(fēng)格和技術(shù)。在我們的比較中,我們將使用PythondCPU風(fēng)格。
ONNX格式定義了一組通用的操作符(機(jī)器學(xué)習(xí)和深度學(xué)習(xí)模型的構(gòu)建塊)和一種通用的文件格式,使AI開發(fā)人員能夠?qū)⒛P团c各種框架、工具、運(yùn)行時(shí)和編譯器一起使用。轉(zhuǎn)換Darknet權(quán)重> Onnx權(quán)重為了使用Onnxruntime運(yùn)行推理,我們必須將*.weights格式轉(zhuǎn)換為*.onnx fomrat。我們將使用專門為將darknet*.weights格式轉(zhuǎn)換為*.pt(PyTorch)和*.onnx(onnx格式)而創(chuàng)建的存儲(chǔ)庫(kù)。
克隆repo并安裝需求。用cfg和weights和img_size參數(shù)運(yùn)行converter.py。python converter.py yolov3.cfg yolov3.weights 1024 1024
將在yolov3.weights目錄中創(chuàng)建一個(gè)yolov3.onnx文件。請(qǐng)記住,在使用ONNX格式進(jìn)行推理時(shí),由于轉(zhuǎn)換過(guò)程的原因,精度會(huì)降低約0.1 mAP%。轉(zhuǎn)換器模仿PyTorch中的Darknet功能,但并非完美無(wú)缺為了支持除yolov3之外的其他darknet架構(gòu)的轉(zhuǎn)換,可以隨意創(chuàng)建issues/PR在我們成功地將模型轉(zhuǎn)換為ONNX格式之后,我們可以使用Onnxruntime運(yùn)行推理。下面是E2E推理的代碼片段:import onnxruntime
import cv2
import numpy as np
# 轉(zhuǎn)換后的onnx權(quán)重
onnx_weights_path = 'yolov3.onnx'
# 指定模型的網(wǎng)絡(luò)大小
network_size = (480, 480)
# 聲明onnxruntime會(huì)話
session = onnxruntime.InferenceSession(onnx_weights_path)
session.get_modelmeta()
input_name = session.get_inputs()[0].name
output_name_1 = session.get_outputs()[0].name
output_name_2 = session.get_outputs()[1].name
# 閱讀圖片
img_path = 'dog.png'
img = cv2.imread(img_path)
image_blob = cv2.dnn.blobFromImage(img, 1 / 255.0, network_size, swapRB=True, crop=False)
# 運(yùn)行推理
layers_result = session.run([output_name_1, output_name_2],
{input_name: image_blob})
layers_result = np.concatenate([layers_result[1], layers_result[0]], axis=1)
# 將layers_result轉(zhuǎn)換為bbox,conf和類
def get_final_predictions(outputs, img, threshold, nms_threshold):
height, width = img.shape[0], img.shape[1]
boxes, confs, class_ids = [], [], []
matches = outputs[np.where(np.max(outputs[:, 4:], axis=1) > threshold)]
for detect in matches:
scores = detect[4:]
class_id = np.a(chǎn)rgmax(scores)
conf = scores[class_id]
center_x = int(detect[0] * width)
center_y = int(detect[1] * height)
w = int(detect[2] * width)
h = int(detect[3] * height)
x = int(center_x - w/2)
y = int(center_y - h / 2)
boxes.a(chǎn)ppend([x, y, w, h])
confs.a(chǎn)ppend(float(conf))
class_ids.a(chǎn)ppend(class_id)
merge_boxes_ids = cv2.dnn.NMSBoxes(boxes, confs, threshold, nms_threshold)
#將layers_result轉(zhuǎn)換為bbox,conf和類
boxes = [boxes[int(i)] for i in merge_boxes_ids]
confs = [confs[int(i)] for i in merge_boxes_ids]
class_ids = [class_ids[int(i)] for i in merge_boxes_ids]
return boxes, confs, class_ids
boxes, confs, class_ids = get_final_predictions(layers_result, img, 0.3, 0.3)
性能比較祝賀你,我們已經(jīng)完成了所有的技術(shù)細(xì)節(jié),你現(xiàn)在應(yīng)該有足夠的知識(shí)來(lái)推理每一個(gè)探測(cè)器,F(xiàn)在讓我們來(lái)討論我們的主要目標(biāo)——性能比較。在PC cpu(英特爾i7第9代)上,分別針對(duì)上述每個(gè)型號(hào)(Yolov3,Tiny-Yolov3)分別測(cè)量了性能**。**對(duì)于opencv和onnxruntime,我們只測(cè)量前向傳播的執(zhí)行時(shí)間,以便將其與前/后進(jìn)程隔離開來(lái)。概要分析:opencvlayers_result = self.net.forward(_output_layers)
Onnxruntimelayers_result = session.run([output_name_1, output_name_2], {input_name: image_blob})
layers_result = np.concatenate([layers_result[1], layers_result[0]], axis=1)
Darknetdarknet detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights -thresh 0.25
判斷Yolov3Yolov3在400張獨(dú)特的圖片上進(jìn)行了測(cè)試。ONNX Detector是推斷我們的Yolov3模型的最快方法。確切地說(shuō),它比opencv-dnn快43%,后者被認(rèn)為是可用的最快的檢測(cè)器之一。
每個(gè)圖像的平均時(shí)間:
Tiny-Yolov3Tiny-Yolov3在600張獨(dú)特的圖像上進(jìn)行了測(cè)試。在我們的Tiny-Yolov3模型上,ONNX探測(cè)器比opencv-dnn快33%。
每個(gè)圖像的平均時(shí)間:
結(jié)論我們已經(jīng)看到 onnxruntime 比 opencvdnn 運(yùn)行的速度要快得多。即使Yolvo3更大,我們也可以用比Tiny-Yolov3更少的時(shí)間運(yùn)行Yolov3。我們擁有必要的工具,可以將在darknet中訓(xùn)練的模型轉(zhuǎn)換為*.onnx格式。

發(fā)表評(píng)論
請(qǐng)輸入評(píng)論內(nèi)容...
請(qǐng)輸入評(píng)論/評(píng)論長(zhǎng)度6~500個(gè)字
最新活動(dòng)更多
-
3月27日立即報(bào)名>> 【工程師系列】汽車電子技術(shù)在線大會(huì)
-
4月30日立即下載>> 【村田汽車】汽車E/E架構(gòu)革新中,新智能座艙挑戰(zhàn)的解決方案
-
5月15-17日立即預(yù)約>> 【線下巡回】2025年STM32峰會(huì)
-
即日-5.15立即報(bào)名>>> 【在線會(huì)議】安森美Hyperlux™ ID系列引領(lǐng)iToF技術(shù)革新
-
5月15日立即下載>> 【白皮書】精確和高效地表征3000V/20A功率器件應(yīng)用指南
-
5月16日立即參評(píng) >> 【評(píng)選啟動(dòng)】維科杯·OFweek 2025(第十屆)人工智能行業(yè)年度評(píng)選
推薦專題
- 1 UALink規(guī)范發(fā)布:挑戰(zhàn)英偉達(dá)AI統(tǒng)治的開始
- 2 北電數(shù)智主辦酒仙橋論壇,探索AI產(chǎn)業(yè)發(fā)展新路徑
- 3 降薪、加班、裁員三重暴擊,“AI四小龍”已折戟兩家
- 4 “AI寒武紀(jì)”爆發(fā)至今,五類新物種登上歷史舞臺(tái)
- 5 國(guó)產(chǎn)智駕迎戰(zhàn)特斯拉FSD,AI含量差幾何?
- 6 光計(jì)算迎來(lái)商業(yè)化突破,但落地仍需時(shí)間
- 7 東陽(yáng)光:2024年扭虧、一季度凈利大增,液冷疊加具身智能打開成長(zhǎng)空間
- 8 地平線自動(dòng)駕駛方案解讀
- 9 封殺AI“照騙”,“淘寶們”終于不忍了?
- 10 優(yōu)必選:營(yíng)收大增主靠小件,虧損繼續(xù)又逢關(guān)稅,能否乘機(jī)器人東風(fēng)翻身?