Python+OpenCV編寫車輛計(jì)數(shù)器系統(tǒng)
介紹
本文,我們將使用歐幾里德距離跟蹤和輪廓的概念在 Python 中使用 OpenCV 構(gòu)建車輛計(jì)數(shù)器系統(tǒng)。
對(duì)象追蹤
對(duì)象跟蹤是在視頻中定位移動(dòng)對(duì)象的過程。在 OpenCV 中有多種技術(shù)可以執(zhí)行對(duì)象跟蹤??梢葬槍?duì) 2 種情況執(zhí)行對(duì)象跟蹤:
- 跟蹤單個(gè)對(duì)象
- 跟蹤多個(gè)對(duì)象
在這里,我們將執(zhí)行多對(duì)象跟蹤方法,因?yàn)槲覀冊(cè)谝粋€(gè)時(shí)間范圍內(nèi)有多輛車。
流行的追蹤算法
DEEP SORT:它是最廣泛使用和非常有效的目標(biāo)跟蹤算法之一,它適用于 YOLO 目標(biāo)檢測(cè),使用卡爾曼濾波器進(jìn)行跟蹤。
質(zhì)心跟蹤算法:質(zhì)心跟蹤算法是一種易于理解且非常有效的算法。這是一個(gè)多步驟的過程。
步驟 1:獲取檢測(cè)到的對(duì)象的邊界框坐標(biāo)并使用邊界框的坐標(biāo)計(jì)算質(zhì)心。
步驟 2:對(duì)于每個(gè)后續(xù)幀,它使用邊界框坐標(biāo)計(jì)算質(zhì)心,并為這些邊界框分配一個(gè) id,并計(jì)算每個(gè)可能的質(zhì)心之間的歐幾里德距離。
步驟 3:我們的假設(shè)是給定對(duì)象可能會(huì)在后續(xù)幀中移動(dòng),并且它們質(zhì)心之間的歐幾里德距離將是與其他對(duì)象相比的最小距離。
步驟 4:將相同的 ID 分配給后續(xù)幀之間的最小移動(dòng)質(zhì)心。
為了檢測(cè)任何運(yùn)動(dòng)物體,我們可以用 frame(t) 減去 frame(t+1)。
對(duì)象跟蹤的應(yīng)用
因?yàn)橛?jì)算機(jī)不斷增長(zhǎng)的計(jì)算能力,對(duì)象跟蹤變得越來(lái)越先進(jìn)。對(duì)象跟蹤有一些主要的用例。
- 交通跟蹤和避免碰撞。
- 人群追蹤
- 無(wú)人在家時(shí)進(jìn)行寵物追蹤
- 導(dǎo)彈跟蹤
- 空氣畫筆
實(shí)現(xiàn)歐幾里得距離跟蹤器
本文使用的所有代碼的源文件和測(cè)試視頻都可以通過這個(gè)鏈接下載
上面討論的所有步驟都可以使用一些數(shù)學(xué)計(jì)算來(lái)執(zhí)行
我們已經(jīng)建立了一個(gè)名為EuclideanDistTracker對(duì)象跟蹤的類。
import math class EuclideanDistTracker: def __init__(self): # Storing the positions of center of the objects self.center_points = {} # Count of ID of boundng boxes # each time new object will be captured the id will be increassed by 1 self.id_count = 0 def update(self, objects_rect): objects_bbs_ids = [] # Calculating the center of objects for rect in objects_rect: x, y, w, h = rect center_x = (x + x + w) // 2 center_y = (y + y + h) // 2 # Find if object is already detected or not same_object_detected = False for id, pt in self.center_points.items(): dist = math.hypot(center_x - pt[0], center_y - pt[1]) if dist < 25: self.center_points[id] = (center_x, center_y) print(self.center_points) objects_bbs_ids.append([x, y, w, h, id]) same_object_detected = True break # Assign the ID to the detected object if same_object_detected is False: self.center_points[self.id_count] = (center_x, center_y) objects_bbs_ids.append([x, y, w, h, self.id_count]) self.id_count += 1 # Cleaning the dictionary ids that are not used anymore new_center_points = {} for obj_bb_id in objects_bbs_ids: var,var,var,var, object_id = obj_bb_id center = self.center_points[object_id] new_center_points[object_id] = center # Updating the dictionary with IDs that is not used self.center_points = new_center_points.copy() return objects_bbs_ids
你可以創(chuàng)建一個(gè)名為tracker.py并粘貼跟蹤器代碼的文件,也可以使用此鏈接直接下載跟蹤器文件。
- update→更新方法需要一個(gè)包含所有邊界框坐標(biāo)的數(shù)組。
- tracker 返回一個(gè)包含 [x,y,w,h, object_id] 的數(shù)組。這里 x,y,w,h 是邊界框的坐標(biāo),object_id 是與該邊界框關(guān)聯(lián)的 id。
在準(zhǔn)備好跟蹤器文件后,我們需要實(shí)現(xiàn)我們的目標(biāo)檢測(cè)器,稍后我們將我們的跟蹤器與目標(biāo)檢測(cè)器綁定。
加載庫(kù)和視頻
從我們已經(jīng)創(chuàng)建的 tracker.py 文件中導(dǎo)入我們的 EuclideanDistTracker 類。
import cv2 import numpy as np from tracker import EuclideanDistTracker tracker = EuclideanDistTracker() cap = cv2.VideoCapture('highway.mp4') ret, frame1 = cap.read() ret, frame2 = cap.read()
cap.read()它返回幀和布爾值,我們需要捕獲幀。
在OpenCV中獲取視頻幀
這個(gè)想法是獲得兩個(gè)后續(xù)幀之間的絕對(duì)差,以便檢測(cè)移動(dòng)對(duì)象。
while cap.isOpened(): # ret, frame = cap.read() diff = cv2.absdiff(frame1, frame2) # this method is used to find the difference bw two frames gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY) blur = cv2.GaussianBlur(gray, (5,5), 0 ) # here i would add the region of interest to count the single lane cars height, width = blur.shape print(height, width) # thresh_value = cv2.getTrackbarPos('thresh', 'trackbar') _, threshold = cv2.threshold(blur, 23, 255, cv2.THRESH_BINARY) dilated = cv2.dilate(threshold, (1,1), iterations=1) contours, _, = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) detections = [] # DRAWING RECTANGLE BOX (Bounding Box) for contour in contours: (x,y,w,h) = cv2.boundingRect(contour) if cv2.contourArea(contour) <300: continue detections.append([x,y,w,h]) boxes_ids = tracker.update(detections) for box_id in boxes_ids: x,y,w,h,id = box_id cv2.putText(frame1, str(id),(x,y-15), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0,0,255), 2) cv2.rectangle(frame1, (x,y),(x+w, y+h), (0,255,0), 2) cv2.imshow('frame',frame1) frame1 = frame2 ret, frame2 = cap.read() key = cv2.waitKey(30) if key == ord('q): break cv2.destroyAllWindows()
cv2.absdiff 此方法用于獲取兩幀之間的絕對(duì)差。
得到幀差后將差值轉(zhuǎn)換為灰度,然后應(yīng)用閾值和輪廓檢測(cè)。
找到的輪廓是所有運(yùn)動(dòng)物體的輪廓
為了避免所有的噪音,我們只采用那些尺寸大于 300 的輪廓。
boxes_ids 包含 (x,y,w,h,id)。
cv2.putText 用于在框架上寫入 Id。
cv2.rectange() 用于繪制邊界框。
輸出:車輛計(jì)數(shù)器系統(tǒng)
結(jié)論
在本文中,我們討論了對(duì)象跟蹤的概念和對(duì)象跟蹤的用例,即車輛計(jì)數(shù)器。
我們討論了對(duì)象跟蹤的一些應(yīng)用,并討論了質(zhì)心跟蹤算法中涉及的步驟,并將其用于車輛計(jì)數(shù)。
基于深度學(xué)習(xí)的對(duì)象跟蹤算法(如用于 YOLO 對(duì)象檢測(cè)的 DEEP SORT 算法)在我們的案例中執(zhí)行得更準(zhǔn)確。
到此這篇關(guān)于Python+OpenCV編寫車輛計(jì)數(shù)器系統(tǒng)的文章就介紹到這了,更多相關(guān)Python OpenCV車輛計(jì)數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
抵御代碼復(fù)雜性使python函數(shù)更加Pythonic技巧示例詳解
這篇文章主要介紹了抵御代碼復(fù)雜性使python函數(shù)更加Pythonic技巧示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01Python程序設(shè)計(jì)入門(1)基本語(yǔ)法簡(jiǎn)介
Python是當(dāng)今日趨流行的一種腳本語(yǔ)言,它比Java更簡(jiǎn)單,比php更強(qiáng)大,并且還適用于做桌面應(yīng)用的開發(fā),這篇文章主要介紹了Python基本語(yǔ)法,需要的朋友可以參考下2014-06-06使用python實(shí)現(xiàn)語(yǔ)音文件的特征提取方法
今天小編就為大家分享一篇使用python實(shí)現(xiàn)語(yǔ)音文件的特征提取方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2019-01-01python開發(fā)實(shí)例之Python的Twisted框架中Deferred對(duì)象的詳細(xì)用法與實(shí)例
這篇文章主要介紹了python開發(fā)實(shí)例之Python的Twisted框架中Deferred對(duì)象的詳細(xì)用法與實(shí)例,需要的朋友可以參考下2020-03-03