前言
本項(xiàng)目效果展示視頻:https://www.bilibili.com/video/BV1E3411G7cP/
1、本項(xiàng)目通過yolov8/yolov7/yolov5 5.0和deepsort實(shí)現(xiàn)了一個(gè)多功能智能交通監(jiān)控系統(tǒng),可為一些同學(xué)的課設(shè)、大作業(yè)等提供參考。分別實(shí)現(xiàn)了不同車輛的跟蹤,統(tǒng)計(jì)不同車型“上行”和“下行”的數(shù)量,實(shí)時(shí)檢測車輛速度,檢測兩車是否發(fā)生碰撞或者距離過近時(shí)進(jìn)行碰撞預(yù)警,檢測車輛是否違規(guī)進(jìn)入專用車道(例如非公交車進(jìn)入公交車專用車道,非法占用高速應(yīng)急車道等行為)。最終檢測效果如下,紅色框內(nèi)區(qū)域即為自定義的公交車專用車道。
2、可訓(xùn)練自己的數(shù)據(jù)集,可以換成yolov8/yolov7/yolov5各種版本的權(quán)重。
一、環(huán)境配置
不熟悉pycharm的anaconda的大兄弟請先看這篇csdn博客,了解pycharm和anaconda的基本操作。
https://blog.csdn.net/ECHOSON/article/details/117220445
anaconda安裝完成之后請切換到國內(nèi)的源來提高下載速度 ,命令如下:
conda config --remove-key channels
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/
conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.bfsu.edu.cn/anaconda/cloud/pytorch/
conda config --set show_channel_urls yes
pip config set global.index-url https://mirrors.ustc.edu.cn/pypi/web/simple
首先創(chuàng)建python3.8的虛擬環(huán)境,請?jiān)诿钚兄袌?zhí)行下列操作:
conda create -n yolov8 python==3.8.5
conda activate yolov8
1、pytorch安裝(gpu版本和cpu版本的安裝)
實(shí)際測試情況是YOLOv8在CPU和GPU的情況下均可使用,不過在CPU的條件下訓(xùn)練那個(gè)速度會令人發(fā)指,所以有條件的小伙伴一定要安裝GPU版本的Pytorch,沒有條件的小伙伴最好是租服務(wù)器來使用。GPU版本安裝的具體步驟可以參考這篇文章:https://blog.csdn.net/ECHOSON/article/details/118420968。
需要注意以下幾點(diǎn):
1、安裝之前一定要先更新你的顯卡驅(qū)動(dòng),去官網(wǎng)下載對應(yīng)型號的驅(qū)動(dòng)安裝
2、30系顯卡只能使用cuda11的版本
3、一定要?jiǎng)?chuàng)建虛擬環(huán)境,這樣的話各個(gè)深度學(xué)習(xí)框架之間不發(fā)生沖突
我這里創(chuàng)建的是python3.8的環(huán)境,安裝的Pytorch的版本是1.8.0,命令如下:
conda install pytorch==1.8.0 torchvision torchaudio cudatoolkit=10.2 # 注意這條命令指定Pytorch的版本和cuda的版本
conda install pytorch==1.8.0 torchvision==0.9.0 torchaudio==0.8.0 cpuonly # CPU的小伙伴直接執(zhí)行這條命令即可
安裝完畢之后,我們來測試一下GPU是否可以有效調(diào)用:
2、pycocotools的安裝
pip install pycocotools-windows
3、其他包的安裝
另外的話大家還需要安裝程序其他所需的包,包括opencv,matplotlib這些包,不過這些包的安裝比較簡單,直接通過pip指令執(zhí)行即可,我們在終端的虛擬環(huán)境中直接執(zhí)行下列指令即可完成包的安裝。
pip install -r requirements.txt
二、車輛檢測、跟蹤、計(jì)數(shù)算法及代碼解讀
1、主函數(shù)各參數(shù)含義
如下代碼所示,可根據(jù)自己需求更改。使用yolov5s.pt、best.pt、或yolov7s.pt/yolov8s.pt預(yù)訓(xùn)練權(quán)重均可,也可以使用自己訓(xùn)練好的權(quán)重,本項(xiàng)目中調(diào)用的是訓(xùn)練好的可以檢測car、truck、bus三個(gè)類別的權(quán)重。
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--weights', type=str, default='best.pt', help='model.pt path') # 加載的v5權(quán)重,可以是公開數(shù)據(jù)集的預(yù)訓(xùn)練權(quán)重,也可以是自己數(shù)據(jù)集訓(xùn)練的權(quán)重
parser.add_argument('--source', type=str, default='IMG_6894.mp4', help='source') # 待檢測的視頻路徑
parser.add_argument('--output', type=str, default='test_out', help='output folder') # output folder
parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
parser.add_argument('--conf-thres', type=float, default=0.6, help='object confidence threshold')
parser.add_argument('--iou-thres', type=float, default=0.5, help='IOU threshold for NMS')
parser.add_argument('--fourcc', type=str, default='mp4v', help='output video codec (verify ffmpeg support)')
parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
parser.add_argument('--view-img', action='store_true', help='display results')
parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
parser.add_argument('--classes', nargs='+', type=int, default=[0, 1, 2], help='filter by class') # car、truck、bus
parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
parser.add_argument('--augment', action='store_true', help='augmented inference')
parser.add_argument("--config_deepsort", type=str, default="deep_sort/configs/deep_sort.yaml")
2、算法實(shí)現(xiàn)
使用yolov8/yolov7/yolov5和deepsort分別實(shí)現(xiàn)車輛的目標(biāo)檢測、跟蹤、計(jì)數(shù),算法流程如下,計(jì)數(shù)原理是將整個(gè)視頻圖像區(qū)域劃分為四個(gè)象限,把第一象限和第三象限的車輛分別認(rèn)為是下行和上行的車輛。計(jì)數(shù)具體代碼實(shí)現(xiàn)時(shí)使用了一系列if-eif條件語句,對目標(biāo)框的中心坐標(biāo)以及四個(gè)象限邊界的位置關(guān)系進(jìn)行判斷。
3、效果展示
以視頻中紅色橫線為基準(zhǔn),統(tǒng)計(jì)car、bus、truck三種車型“上行”和“下行”的數(shù)量和總共的數(shù)量,并顯示在圖像左上角,同時(shí)將車型、車輛ID打印在車輛檢測框的正上方。可以拓展到行人跟蹤等多個(gè)領(lǐng)域,只要將訓(xùn)練好的所需類別的yolov8/yolov7/yolov5權(quán)重替換掉,代碼里面做一些修改就行了。
三、車輛測速算法及代碼解讀
1、算法流程
首先使用提前設(shè)定好的車輛真實(shí)寬度和檢測出來的車輛像素寬度求出真實(shí)距離和像素距離的比值,再使用每輛車的前后兩幀框的中心坐標(biāo)計(jì)算出兩幀之間移動(dòng)的像素距離。利用這個(gè)比值和像素距離做映射,就可以求出兩幀之間車輛移動(dòng)的真實(shí)距離。然后距離除以兩幀之間的時(shí)間,就是速度了。本測速算法中將車輛真實(shí)移動(dòng)距離與像素移動(dòng)距離看成是線性關(guān)系,僅在監(jiān)控相機(jī)軸線與車輛移動(dòng)方向垂直時(shí)才能成立,并且檢測出來的車輛框在空間上會產(chǎn)生一定形變,使得真實(shí)距離和像素距離的映射關(guān)系不準(zhǔn)確。有興趣的同學(xué)可以在代碼中加入透視變換,將圖像變成類似于遙感數(shù)據(jù)的俯瞰圖,實(shí)現(xiàn)測速后再將圖像變換為原始圖像視角,就能實(shí)現(xiàn)比較準(zhǔn)確的車輛測速了。
2、核心代碼
我的項(xiàng)目將測速代碼封裝到了Estimated_speed()函數(shù)里面,有詳細(xì)注釋,調(diào)用即可。
def Estimated_speed(locations, fps, width):
present_IDs = []
prev_IDs = []
work_IDs = []
work_IDs_index = []
work_IDs_prev_index = []
work_locations = [] # 當(dāng)前幀數(shù)據(jù):中心點(diǎn)x坐標(biāo)、中心點(diǎn)y坐標(biāo)、目標(biāo)序號、車輛類別、車輛像素寬度
work_prev_locations = [] # 上一幀數(shù)據(jù),數(shù)據(jù)格式相同
speed = []
for i in range(len(locations[1])):
present_IDs.append(locations[1][i][2]) # 獲得當(dāng)前幀中跟蹤到車輛的ID
for i in range(len(locations[0])):
prev_IDs.append(locations[0][i][2]) # 獲得前一幀中跟蹤到車輛的ID
for m, n in enumerate(present_IDs):
if n in prev_IDs: # 進(jìn)行篩選,找到在兩幀圖像中均被檢測到的有效車輛ID,存入work_IDs中
work_IDs.append(n)
work_IDs_index.append(m)
for x in work_IDs_index: # 將當(dāng)前幀有效檢測車輛的信息存入work_locations中
work_locations.append(locations[1][x])
for y, z in enumerate(prev_IDs):
if z in work_IDs: # 將前一幀有效檢測車輛的ID索引存入work_IDs_prev_index中
work_IDs_prev_index.append(y)
for x in work_IDs_prev_index: # 將前一幀有效檢測車輛的信息存入work_prev_locations中
work_prev_locations.append(locations[0][x])
for i in range(len(work_IDs)):
speed.append(
math.sqrt((work_locations[i][0] - work_prev_locations[i][0]) ** 2 + # 計(jì)算有效檢測車輛的速度,采用線性的從像素距離到真實(shí)空間距離的映射
(work_locations[i][1] - work_prev_locations[i][1]) ** 2) * # 當(dāng)視頻拍攝視角并不垂直于車輛移動(dòng)軌跡時(shí),測算出來的速度將比實(shí)際速度低
width[work_locations[i][3]] / (work_locations[i][4]) * fps / 5 * 3.6 * 2)
for i in range(len(speed)):
speed[i] = [round(speed[i], 1), work_locations[i][2]] # 將保留一位小數(shù)的單位為km/h的車輛速度及其ID存入speed二維列表中
return speed
3、效果展示
將計(jì)算出來的速度實(shí)時(shí)顯示在車輛正上方。可以針對不同的道路環(huán)境設(shè)定一個(gè)速度閾值,例如高速上通常限速為120km/h,將每一幀中各車輛的速度和ID存到一個(gè)列表里面,讀取列表,和設(shè)定的速度閾值進(jìn)行比較。若超速,則發(fā)出警告。需要注意的是,每判斷完一幀后,要將這個(gè)列表進(jìn)行清空防止幀之間的數(shù)據(jù)混淆,同時(shí)防止列表溢出(雖然不大可能)。
四、車輛碰撞檢測算法及代碼解讀
1、算法流程
首先將yolov8/yolov7/yolov5檢測出來的車輛框通過兩層for循環(huán)嵌套讀取出來,將任意兩個(gè)車輛框進(jìn)行兩兩匹配,再通過一系列的if和elif語句判斷兩框位置關(guān)系,若兩框相交區(qū)域的寬度或高度超過一定像素t,或存在包含與被包含關(guān)系,則判定為碰撞,將其車輛ID存入列表中。t值可以按照實(shí)際需求自己調(diào)整,t值越大,碰撞越不容易檢出。當(dāng)t為一個(gè)較小的值時(shí),可當(dāng)做碰撞預(yù)警功能來使用。
2、核心代碼
本項(xiàng)目將這個(gè)功能封裝到了find_accidents()函數(shù)里面,直接調(diào)用即可。核心判斷語句代碼如下:
# 通過A、B框位置關(guān)系判斷其是否發(fā)生碰撞,若相交、存在包含關(guān)系,則判定為碰撞,將其索引加入crash_index列表中。
if (B_xmin < A_xmin + t and A_xmin + t < B_xmax - t and A_xmax > B_xmax - t) and (
B_ymin < A_ymin + t and A_ymin + t < B_ymax - t and A_ymax > B_ymax - t): # 01
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (B_xmin < A_xmin + t and A_xmin + t < B_xmax - t and A_xmax > B_xmax - t) and (
A_ymin < B_ymin and B_ymin < B_ymax and A_ymax < B_ymax): # 02
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (B_xmin < A_xmin + t and A_xmin + t < B_xmax - t and A_xmax > B_xmax - t) and (
A_ymin < B_ymin + t and B_ymin + t < A_ymax - t and B_ymax > A_ymax - t): # 03
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (A_xmin < B_xmin and B_xmin < B_xmax and A_xmax > B_xmax) and (
B_ymin < A_ymin + t and A_ymin + t < B_ymax - t and A_ymax > B_ymax - t): # 04
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (A_xmin < B_xmin + t and B_xmin + t < A_xmax - t and B_xmax > A_xmax - t) and (
B_ymin < A_ymin + t and A_ymin + t < B_ymax - t and A_ymax > B_ymax - t): # 05
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (A_xmin < B_xmin + t and B_xmin + t < A_xmax - t and B_xmax > A_xmax - t) and (
A_ymin < B_ymin and B_ymin < B_ymax and A_ymax > B_ymax): # 06
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (A_xmin < B_xmin + t and B_xmin + t < A_xmax - t and B_xmax > A_xmax - t) and (
A_ymin < B_ymin + t and B_ymin + t < A_ymax - t and B_ymax > A_ymax - t): # 07
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (A_xmin < B_xmin and B_xmin < B_xmax and A_xmax > B_xmax) and (
A_ymin < B_ymin + t and B_ymin + t < A_ymax - t and B_ymax > A_ymax - t): # 08
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (A_xmin < B_xmin and B_xmin < A_xmax and B_xmax > A_xmax) and (
B_ymin < A_ymin and A_ymin < A_ymax and B_ymax > A_ymax): # 09
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (B_xmin < A_xmin and A_xmin < B_xmax and A_xmax > B_xmax) and (
B_ymin < A_ymin and A_ymin < A_ymax and B_ymax > A_ymax): # 10
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (B_xmin < A_xmin and A_xmin < A_xmax and B_xmax > A_xmax) and (
A_ymin < B_ymin and B_ymin < A_ymax and B_ymax > A_ymax): # 11
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
elif (B_xmin < A_xmin and A_xmin < A_xmax and B_xmax > A_xmax) and (
B_ymin < A_ymin and A_ymin < B_ymax and A_ymax > B_ymax): # 12
is_accident_happen.append([A_class, B_class])
crash_index.append([i, j])
3、效果展示
當(dāng)兩輛車距離過近,導(dǎo)致檢測框出現(xiàn)相交、重疊、甚至包含關(guān)系時(shí)發(fā)出碰撞警報(bào)。這里定義了一個(gè)像素閾值t,可通過t值大小來調(diào)節(jié)碰撞檢測的靈敏程度。
def find_accidents(rects):
is_accident_happen = []
t = 3000 # 設(shè)定閾值,這個(gè)值越大,碰撞越不容易檢出。設(shè)置一個(gè)較小的值時(shí),可當(dāng)做碰撞預(yù)警功能來使用。
crash_index = []
五、違規(guī)進(jìn)入專用車道檢測算法及代碼解讀
1、算法流程
首先使用opencv截取視頻的第一幀作為背景,再通過python的交互模式繪制專用車道矩形區(qū)域(此處以違規(guī)進(jìn)入公交車道檢測為例),鼠標(biāo)按順時(shí)針方向依次點(diǎn)擊矩形框的四個(gè)頂點(diǎn)即可。專用區(qū)域繪制結(jié)束后會將四個(gè)頂點(diǎn)坐標(biāo)以及矩形四條邊的直線方程保存至根目錄下的car_line.txt中。這一步結(jié)束后調(diào)用detect()函數(shù),讀取car_line.txt,利用車輛矩形框的中心點(diǎn)坐標(biāo)和專用車道區(qū)域的位置關(guān)系進(jìn)行判斷。若非公交車違規(guī)進(jìn)入公交車專用車道,則發(fā)出警告。判斷邏輯如下:
2、核心代碼
# 判斷車輛框的中心是否在繪制的矩形區(qū)域內(nèi)且該車輛是否為公交車,若不是公交車,則違規(guī)駛?cè)牍卉嚨馈?/span>
# 算法思路為將目標(biāo)框中心點(diǎn)坐標(biāo)依次代入四條直線方程內(nèi),使用中心點(diǎn)縱坐標(biāo)分別與代入計(jì)算出來的值進(jìn)行比較,滿足所列大小關(guān)系即該點(diǎn)在矩形框內(nèi)部。
for box_center in box_centers:
if (k[0] * box_center[0] + b[0] <= box_center[1] and k[1] * box_center[0] + b[1] >= box_center[1]
and k[2] * box_center[0] + b[2] >= box_center[1] and k[3] * box_center[0] + b[3] <= box_center[1] and (
box_center[3] != 1)):
cv2.putText(im0, 'Entering illegally!', (int(box_center[0] - 140), int(box_center[1])),
cv2.FONT_HERSHEY_PLAIN, 1.5, [0, 0, 255], 2)
3、效果展示
六、總結(jié)及源碼獲取
1、總結(jié)
其中違規(guī)進(jìn)入專用車道檢測這個(gè)功能還可以再完善一下,比如一些地區(qū)的公交專用車道設(shè)置了使用時(shí)間段,在時(shí)間段之外允許非公交車進(jìn)入,可以通過調(diào)用接口獲取系統(tǒng)時(shí)間來實(shí)現(xiàn)更好的判斷,這個(gè)功能也可以拓展到更多的應(yīng)用場景里面,如檢測高速上常見的違規(guī)進(jìn)入應(yīng)急車道等行為。在車輛分布密集時(shí)有一些漏檢,導(dǎo)致統(tǒng)計(jì)的車輛數(shù)目會比實(shí)際的略少,可以使用自己的數(shù)據(jù)打標(biāo)簽后針對性fine tune一下。
2、項(xiàng)目資源獲取(yolov8/yolov7/yolov5版本均可提供)
項(xiàng)目內(nèi)容:
包含完整word版本說明文檔,可用于寫論文、課設(shè)報(bào)告的參考。
資源獲?。?mark hidden color="red">文章來源:http://www.zghlxwxcb.cn/news/detail-406882.html
獲取整套代碼、測試視頻、訓(xùn)練好的權(quán)重和說明文檔(有償)
上交碩士,技術(shù)夠硬,也可以指導(dǎo)深度學(xué)習(xí)畢設(shè)、大作業(yè)等。
--------------->qq------------
3582584734
------------------------------
文章來源地址http://www.zghlxwxcb.cn/news/detail-406882.html
到了這里,關(guān)于智能交通系統(tǒng)-yolov5+deepsort車輛跟蹤、計(jì)數(shù)、測速、碰撞檢測、違規(guī)駛?cè)霗z測(算法-畢業(yè)設(shè)計(jì))的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!