日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

【yolov3目标检测】(3) opencv+yolov3 检测交通路况,附python完整代码

發布時間:2023/11/27 生活经验 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【yolov3目标检测】(3) opencv+yolov3 检测交通路况,附python完整代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

各位同學好,今天和大家分享一下如何使用 opencv 調用 yolov3 模型,加載網絡權重,很方便地實現 yolov3 目標檢測。先放張圖看效果。

使用的網上找的行車記錄儀視頻做測試,數據集采用COCO數據集,檢測效果還是不錯的。


1. 預先準備

首先需要導入 COCO 數據集的分類名文件 'coco.names',以及yolov3的網絡結構 'yolo.cfg',網絡的權重參數 'yolo.weights',這些文件以及本案例的代碼我給大家都提供好了,有需要的自取。

鏈接:https://pan.baidu.com/s/12iPJTjiN7SIBJ7hpHomn_w?

提取碼:p548

yolov3 使用 Darknet53 網絡模型,這個網絡我之前復現過,感興趣的可以看一下:https://blog.csdn.net/dgvv4/article/details/121997986

使用?cv2.dnn.readNetFromDarknet() 從opencv中讀取網絡模型,傳入網絡結構和權重參數。

由于我這個視頻比較短,因此設置視頻重復播放,使用 cv2.CAP_PROP_POS_FRAMES 獲取當前視頻所在第幾幀,使用 cv2.CAP_PROP_FRAME_COUNT 獲取該視頻一共有多少幀。如果播放到了最后一幀,那就讓當前幀=0,從頭開始。

代碼如下,net 配置完成,播放視頻圖像。

import numpy as np
import cv2
import time#(1)加載預訓練的COCO數據集
classesFile = 'coco.names'  # 指定coco數據集分類名所在路徑
classNames = []  # 創建列表,存放coco數據集的分類名稱# 打開數據集名稱的文件
with open(classesFile, 'rt') as f:  #讀取文本文件classNames = f.read().rstrip('\n').split('\n')  # 通過換行符來拆分,再讀入# 加載yolov3結構cfg文件
modelConfiguration = 'yolov3.cfg'
# 加載yolov3網絡權重
modelWeights = 'yolov3.weights'#(2)構建網絡結構
# 導入darknet53網絡,傳入cfg文件和網絡權重
net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
# 申明使用opencv作為后端
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
# 申明使用CPU計算
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)#(3)獲取攝像頭
videoFile = 'C:\\GameDownload\\Deep Learning\\yolov3video.mp4'
cap = cv2.VideoCapture(videoFile) # 0代表電腦自帶的攝像頭,代表外接攝像頭 pTime = 0  # 設置第一幀開始處理的起始時間#(4)處理幀圖像
while True:# 接收圖片是否導入成功、幀圖像success, img = cap.read()# 改變圖像大小img = cv2.resize(img, (1280,720))# 視頻較短,循環播放if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):# 如果當前幀==總幀數,那就重置當前幀為0cap.set(cv2.CAP_PROP_POS_FRAMES, 0)#(5)顯示圖像# 查看FPScTime = time.time() #處理完一幀圖像的時間fps = 1/(cTime-pTime)pTime = cTime  #重置起始時間# 在視頻上顯示fps信息,先轉換成整數再變成字符串形式,文本顯示坐標,文本字體,文本大小cv2.putText(img, str(int(fps)), (70,50), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,0), 3)  # 顯示圖像,輸入窗口名及圖像數據cv2.imshow('img', img)    if cv2.waitKey(20) & 0xFF==27:  #每幀滯留20毫秒后消失,ESC鍵退出break# 釋放視頻資源
cap.release()
cv2.destroyAllWindows()

2. 獲取檢測框信息

2.1 確定輸入及輸出

先看下面代碼中的第(6)步,圖像傳入神經網絡之前先進行預處理?cv2.dnn.blobFromImage(),包括減均值,比例縮放,裁剪,交換通道等,返回一個4通道的blob(blob可以簡單理解為一個N維的數組)。之后使用 net.setInput() 將blob類型圖像作為網絡輸入。

cv2.dnn.blobFromImage(img, scalefactor, size, mean, swapRB, crop, ddepth)'''
image: 輸入圖像
scalefactor: 圖像各通道數值的縮放比例,默認=1
size: 輸出圖像的空間尺寸,如size=(200,300)表示高h=300,寬w=200
mean: 用于各通道減去的值,以降低光照的影響,例:(image為BGR的3通道的圖像,mean=[104.0, 177.0, 123.0],表示B通道的值-104,G-177,R-123)
swapRB: 交換RB通道,默認為False。(cv2.imread讀取的是彩圖是BGR通道)
crop: 圖像裁剪,默認為False。當值為True時,先按比例縮放,然后從中心裁剪成size尺寸
ddepth: 輸出的圖像深度,可選CV_32F 或者 CV_8U.
'''

由下圖的 Darknet53 網絡結構圖可知,網絡有三個輸出層,輸出的shape分別為?[52,52,255] 用于預測小目標[26,26,255] 用于預測中等大小的目標[13,13,255] 用于預測大目標。因此我們通過?net.getUnconnectedOutLayers() 就能知道這三個輸出層處于網絡中的第幾層,得到的返回結果是?[200, 227, 254]通過?net.getLayerNames() 只要輸入層的索引就能得到該索引所對應的層的名稱。得到輸出層的層名稱后,將其傳入 net.forward() 中,就能找到輸出層的輸出結果。

到這里就完成了網絡模型的輸入 blob,得到了模型的三個輸出?outputs,打印輸出結果的相關信息如下。以 outputs[0].shape =(300,85)為例,?300代表檢測框的數量,85代表:中心點坐標 x,y;框的寬高 w,h;置信度 c;80 個分類各自的概率

print(outputs[0].shape)  # (300, 85) 
print(outputs[1].shape)  # (1200, 85)
print(outputs[2].shape)  # (4800, 85)
print(outputs[0][0])  # 打印第0個檢測框所包含的信息'''
(300, 85)
(1200, 85)
(4800, 85)
[4.9195103e-02 5.5935599e-02 6.5290880e-01 1.8459144e-01 8.2010246e-080.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+000.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00 0.0000000e+00]
'''

2.2 獲取檢測框信息

接下來我們就看到下面代碼中的第(4)步,現在有了每個區域的預測結果 outputs,需要從中找到和每個物體對應的最合適的檢測框。

注意一下,img.shape 是先指定圖像的高,再指定寬,(h, w, c),不要搞錯了。

其中 output 遍歷三個輸出層,每個輸出層包含n個檢測框,每個框包含85項信息det 遍歷每一層的n個檢測框,det 包含85項信息。我們需要找到每個框屬于哪個分類,以及該框屬于該分類的概率 confidence。如果該分類概率大于閾值 confThreshold 證明找到了,這時候就將該框的左上角坐標(x,y),框的寬w和高h,及置信度 confidence 保存下來。

這里需要注意的是,每個框的85項信息中的其四個信息:中心坐標和寬高,都是歸一化之后的比例坐標和比例寬高。需要將比例寬高乘上原圖像寬高才能得到檢測框的真實寬高

在第二節的代碼中補充。

import numpy as np
import cv2
import time#(1)加載預訓練的COCO數據集
classesFile = 'coco.names'  # 指定coco數據集分類名所在路徑
classNames = []  # 創建列表,存放coco數據集的分類名稱# 打開數據集名稱的文件
with open(classesFile, 'rt') as f:  #讀取文本文件classNames = f.read().rstrip('\n').split('\n')  # 通過換行符來拆分,再讀入# 加載yolov3結構cfg文件
modelConfiguration = 'yolov3.cfg'
# 加載yolov3網絡權重
modelWeights = 'yolov3.weights'# 確定輸入圖像的寬和高
wInput, hInput = 320, 320# 自定義目標檢測的最小置信度
confThreshold = 0.5#(2)構建網絡結構
# 導入darknet53網絡,傳入cfg文件和網絡權重
net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
# 申明使用opencv作為后端
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
# 申明使用CPU計算
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)#(3)獲取攝像頭
videoFile = 'C:\\GameDownload\\Deep Learning\\trafficvideo2.mp4'
cap = cv2.VideoCapture(videoFile) # 0代表電腦自帶的攝像頭,代表外接攝像頭 pTime = 0  # 設置第一幀開始處理的起始時間#(4)定義函數用于檢測目標,獲取檢測框信息,以及分類類別
def findObjects(outputs, img):# 圖像的高度、寬度、通道數hT, wT, cT = img.shape# 定義一個列表存放檢測框的中心點坐標和寬高bbox = []# 定義列表存放分類的名稱的索引classIds = []# 定義列表存放置信度confs = [] # 如果找到目標了,就將檢測框的信息存放起來# 遍歷三個輸出層for output in outputs:# 遍歷輸出層的85項信息for det in output:  # det是數組類型# 在80個分類中找到哪個分類的值是最高的score = det[5:]  # 忽略檢測框的x,y,w,h,c# 找到分類值最大對應的索引號classId = np.argmax(score)# 找到分類概率最大值的索引對應的值confidence = score[classId]# 如果檢測置信度大于規定的閾值,表明檢測到了物體if confidence > confThreshold:# 記錄檢測框的寬和高,這里的寬高是歸一化之后的比例寬度和高度w, h = int(det[2]*wT), int(det[3]*hT)  # 比例寬高轉為像素寬高,像素寬高是整數# 記錄檢測框的左上角坐標x, y = det[0]*wT-w//2, det[1]*hT-h//2# 將檢測框的信息保存起來bbox.append([x, y, w, h])# 將目標屬于哪個類別的索引保存下來classIds.append(classId)# 保存檢測框的置信度,檢測出某個目標的概率confs.append(float(confidence))# 打印檢測框信息print('classids:', classIds, 'confidence:', confs, 'bbox:', bbox)#(5)處理幀圖像
while True:# 接收圖片是否導入成功、幀圖像success, img = cap.read()# 改變圖像大小img = cv2.resize(img, (1280,720))# 視頻較短,循環播放if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):# 如果當前幀==總幀數,那就重置當前幀為0cap.set(cv2.CAP_PROP_POS_FRAMES, 0)#(6)將img圖片轉換成blob塊類型,網絡只接受這種類型# 輸入img圖像,,圖像寬w高h,默認參數[0,0,0],,blob = cv2.dnn.blobFromImage(img, 1/255, (wInput,hInput), [0,0,0], 1, crop=False)# 將轉換類型后的圖像作為輸入數據net.setInput(blob)# 獲得網絡各層的名稱,由于網絡會輸出最后三層的結果,用于定位輸出層layerNames = net.getLayerNames()  # 得到網絡所有層的名稱# 提取輸出層,返回輸出層是第幾層,層數是從1開始,索引是從0開始# net.getUnconnectedOutLayers()  # [200, 227, 254]outputNames = []  # 存放輸出層名稱# 得到輸出層在網絡中屬于第幾層for outindex in net.getUnconnectedOutLayers():# 得到輸出層的名稱,outindex是第幾層(從1開始),傳入的是索引(從0開始)outputNames.append(layerNames[outindex-1])# 獲取輸出層返回結果outputs = net.forward(outputNames)print(outputs[0].shape)  # (300, 85)  300代表檢測框的數量,85代表:中心點坐標x,y,框的寬高w,h,置信度c,80個分類各自的概率print(outputs[1].shape)  # (1200, 85)print(outputs[2].shape)  # (4800, 85)print(outputs[0][0])  # 打印第0個檢測框所包含的信息#(7)目標檢測findObjects(outputs, img)    #(8)顯示圖像# 查看FPScTime = time.time() #處理完一幀圖像的時間fps = 1/(cTime-pTime)pTime = cTime  #重置起始時間# 在視頻上顯示fps信息,先轉換成整數再變成字符串形式,文本顯示坐標,文本字體,文本大小cv2.putText(img, str(int(fps)), (70,50), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,0), 3)  # 顯示圖像,輸入窗口名及圖像數據cv2.namedWindow("img", 0)  # 窗口大小可調整cv2.imshow('img', img)    if cv2.waitKey(20) & 0xFF==27:  #每幀滯留20毫秒后消失,ESC鍵退出break# 釋放視頻資源
cap.release()
cv2.destroyAllWindows()

打印得到的檢測框信息

classids: [2, 7, 7, 2, 2, 2, 2, 2, 2] 
confidence: [0.8474083542823792, 0.6886539459228516, 0.7003887891769409, 0.9768345952033997, 0.7150803804397583, 0.7982962131500244, 0.7913717031478882, 0.9718230962753296, 0.8747612833976746] 
bbox: [[769.3665313720703, 398.1743869781494, 110, 88], [348.8137969970703, 387.51572608947754, 98, 70], [347.2083282470703, 388.56964111328125, 101, 71], [453.0018081665039, 409.030611038208, 32, 26], [625.3595275878906, 397.98907947540283, 67, 57], [681.5968627929688, 405.41797828674316, 37, 36], [694.1919250488281, 410.92028617858887, 37, 30], [760.8668212890625, 402.86146450042725, 124, 75], [777.7303924560547, 401.2068338394165, 112, 77]]

3. 顯示預測框,完成目標檢測

進行完上面的操作后,我們現在得到一個物體上可能有很多的檢測框都滿足條件,接下來采用 NMS 非極大值抑制?cv2.dnn.NMSBoxes()搜索出局部最大值,將置信度最大的框保存,其余剔除,確保每個目標至少有一個框。

cv2.dnn.NMSBoxes(bboxes, scores, score_threshold, nms_threshold, eta=None, top_k=None)'''
bboxes:檢測框信息 [x,y,w,h]
scores:每個待處理檢測框的置信度
score_threshold:用于過濾檢測框的置信度閾值
nms_threshold:NMS閾值
eta:自適應閾值公式中的相關系數
top_k: 如果 top_k>0,則保留最多 top_k 個邊界框索引值
'''

接下去就能使用矩形框繪制函數?cv2.rectangle() 把每個檢測框繪制出來。

在上一節的代碼中補充。

import numpy as np
import cv2
import time#(1)加載預訓練的COCO數據集
classesFile = 'C:\\Users\\admin\\.spyder-py3\\test\\機器視覺\\yolov3\\coco.names'  # 指定coco數據集分類名所在路徑
classNames = []  # 創建列表,存放coco數據集的分類名稱# 打開數據集名稱的文件
with open(classesFile, 'rt') as f:  #讀取文本文件classNames = f.read().rstrip('\n').split('\n')  # 通過換行符來拆分,再讀入# 加載yolov3結構cfg文件
modelConfiguration = 'yolov3.cfg'
# 加載yolov3網絡權重
modelWeights = 'yolov3.weights'# 確定輸入圖像的寬和高
wInput, hInput = 320, 320# 自定義目標檢測的最小置信度
confThreshold = 0.5# 自定義非極大值抑制的參數
nms_threshold = 0.3#(2)構建網絡結構
# 導入darknet53網絡,傳入cfg文件和網絡權重
net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights)
# 申明使用opencv作為后端
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
# 申明使用CPU計算
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)#(3)獲取攝像頭
videoFile = 'C:\\GameDownload\\Deep Learning\\trafficvideo1.mp4'
cap = cv2.VideoCapture(videoFile) # 0代表電腦自帶的攝像頭,代表外接攝像頭 #(4)定義函數用于檢測目標,獲取檢測框信息,以及分類類別
def findObjects(outputs, img):# 圖像的高度、寬度、通道數hT, wT, cT = img.shape  # 先保存高度,再保存寬度# 定義一個列表存放檢測框的中心點坐標和寬高bbox = []# 定義列表存放分類的名稱的索引classIds = []# 定義列表存放置信度confs = [] # 如果找到目標了,就將檢測框的信息存放起來# 遍歷三個輸出層for output in outputs:# 遍歷輸出層的85項信息for det in output:  # det是數組類型# 在80個分類中找到哪個分類的值是最高的score = det[5:]  # 忽略檢測框的x,y,w,h,c# 找到分類值最大對應的索引號classId = np.argmax(score)# 找到分類概率最大值的索引對應的值confidence = score[classId]# 如果檢測置信度大于規定的閾值,表明檢測到了物體if confidence > confThreshold:# 記錄檢測框的寬和高,這里的寬高是歸一化之后的比例寬度和高度w, h = int(det[2]*wT), int(det[3]*hT)  # 比例寬高轉為像素寬高,像素寬高是整數# 記錄檢測框的左上角坐標x, y = int(det[0]*wT-w/2), int(det[1]*hT-h/2)# 將檢測框的信息保存起來bbox.append([x, y, w, h])# 將目標屬于哪個類別的索引保存下來classIds.append(classId)# 保存檢測框的置信度,檢測出某個目標的概率confs.append(float(confidence))#(5)消除重疊的矩形框,非極大值抑制indices = cv2.dnn.NMSBoxes(bbox, confs, confThreshold, nms_threshold)  # 返回檢測框的索引 # 遍歷索引繪制矩形框for i in indices:# 在所有包含目標的矩形框中找到最符合的矩形框box = bbox[i]# 提取矩形框的信息x, y, w, h = box[0], box[1], box[2], box[3]# 繪制矩形框cv2.rectangle(img, (x,y), (x+w,y+h), (255,255,0), 2)# 顯示文本cv2.putText(img, f'{classNames[classIds[i]]}',(x,y+h+18), cv2.FONT_HERSHEY_COMPLEX, 0.8, (0,255,0), 2)cv2.putText(img, f'{int(confs[i]*100)}%',(x,y-8), cv2.FONT_HERSHEY_COMPLEX, 0.8, (0,0,255), 2)  #(6)處理幀圖像
while True:# 接收圖片是否導入成功、幀圖像success, img = cap.read()# 改變圖像大小img = cv2.resize(img, (1280,720))# 視頻較短,循環播放if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT):# 如果當前幀==總幀數,那就重置當前幀為0cap.set(cv2.CAP_PROP_POS_FRAMES, 0)#(7)將img圖片轉換成blob塊類型,網絡只接受這種類型# 輸入img圖像,,圖像寬w高h,默認參數[0,0,0],,blob = cv2.dnn.blobFromImage(img, 1/255, (wInput,hInput), [0,0,0], 1, crop=False)# 將轉換類型后的圖像作為輸入數據net.setInput(blob)# 獲得網絡各層的名稱,由于網絡會輸出最后三層的結果,用于定位輸出層layerNames = net.getLayerNames()  # 得到網絡所有層的名稱# 提取輸出層,返回輸出層是第幾層,層數是從1開始,索引是從0開始# net.getUnconnectedOutLayers()  # [200, 227, 254]outputNames = []  # 存放輸出層名稱# 得到輸出層在網絡中屬于第幾層for outindex in net.getUnconnectedOutLayers():# 得到輸出層的名稱,outindex是第幾層(從1開始),傳入的是索引(從0開始)outputNames.append(layerNames[outindex-1])# 獲取輸出層返回結果outputs = net.forward(outputNames)#(8)目標檢測findObjects(outputs, img)    #(9)顯示圖像    # 顯示圖像,輸入窗口名及圖像數據cv2.namedWindow("img", 0)  # 窗口大小可調整cv2.imshow('img', img)    if cv2.waitKey(1) & 0xFF==27:  #每幀滯留20毫秒后消失,ESC鍵退出break# 釋放視頻資源
cap.release()
cv2.destroyAllWindows()

檢測結果如下:

總結

以上是生活随笔為你收集整理的【yolov3目标检测】(3) opencv+yolov3 检测交通路况,附python完整代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。