叉乘:基于虚拟线圈法的车流量统计
日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)
CNN:RCNN、SPPNet、Fast RCNN、Faster RCNN、YOLO V1 V2 V3、SSD、FCN、SegNet、U-Net、DeepLab V1 V2 V3、Mask RCNN
自動駕駛:車道線檢測、車速檢測、實時通行跟蹤、基于視頻的車輛跟蹤及流量統計
車流量檢測實現:多目標追蹤、卡爾曼濾波器、匈牙利算法、SORT/DeepSORT、yoloV3、虛擬線圈法、交并比IOU計算
多目標追蹤:DBT、DFT、基于Kalman和KM算法的后端優化算法、SORT/DeepSORT、基于多線程的單目標跟蹤的多目標跟蹤算法KCF
計算交并比IOU、候選框不同表示方式之間的轉換
卡爾曼濾波器
卡爾曼濾波器實踐
目標估計模型-卡爾曼濾波
匈牙利算法
數據關聯:利用匈牙利算法對目標框和檢測框進行關聯
SORT、DeepSORT
多目標追蹤
yoloV3模型
基于yoloV3的目標檢測
叉乘:基于虛擬線圈法的車流量統計
視頻中的車流量統計
4.9. 車流量統計
學習目標
- 了解車流量統計的方法
- 實現車流量檢測
1.基于虛擬線圈法的車輛統計
基于虛擬線圈的車流量統計算法原理與交通道路上的常見的傳統的物理線圈類似,由于物理線圈需要埋設在路面之下,因此會有安裝、維護費用高,造成路面破壞等問題,而采用基于視頻的虛擬線圈的車輛計數方法完全避免了以上問題,且可以針對多個感興趣區域進行檢測。
虛擬線圈車輛計數法的原理是在采集到的交通流視頻中,在需要進行車輛計數的道路或路段上設置一條或一條以上的檢測線對通過車輛進行檢測,從而完成計數工作。檢測線的設置原則一般是在檢測車道上設置一條垂直于車道線,居中的虛擬線段,通過判斷其與通過車輛的相對位置的變化,完成車流量統計的工作。如下圖所示,綠色的線就是虛擬檢測線:
在該項目中我們進行檢測的方法是,計算前后兩幀圖像的車輛檢測框的中心點連線,若該連線與檢測線相交,則計數加一,否則計數不變。
那怎么判斷兩條線段是否相交呢?
假設有兩條線段AB,CD,若AB,CD相交,我們可以確定:
1.線段AB與CD所在的直線相交,即點A和點B分別在直線CD的兩邊;
2.線段CD與AB所在的直線相交,即點C和點D分別在直線AB的兩邊;
上面兩個條件同時滿足是兩線段相交的充要條件,所以我們只需要證明點A和點B分別在直線CD的兩邊,點C和點D分別在直線AB的兩邊,這樣便可以證明線段AB與CD相交了。
在上圖中,線段AB與線段CD相交,于是我們可以得到兩個向量AC,AD,C和D分別在AB的兩邊,向量AC在向量AB的逆時針方向,AB×AC > 0;向量AD在向量AB的順時針方向,AB×AD < 0,兩叉乘結果異號。
這樣,方法就出來了:如果線段CD的兩個端點C和D,與另一條線段的一個端點(A或B,只能是其中一個)連成的向量,與向量AB做叉乘,若結果異號,表示C和D分別在直線AB的兩邊,若結果同號,則表示CD兩點都在AB的一邊,則肯定不相交。
所以我們利用叉乘的方法來判斷車輛是否經過檢測線。
2.實現
實現車流量檢測的代碼如下:
1.檢測AB和CD兩條直線是否相交
# 檢測AB和CD兩條直線是否相交 def intersect(A, B, C, D):return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D)# 計算有A,B,C三點構成的向量CA,BA之間的關系, def ccw(A, B, C):return (C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0])總結
?
""" 基于虛擬線圈法的車輛統計1.基于虛擬線圈的車流量統計算法原理與交通道路上的常見的傳統的物理線圈類似,由于物理線圈需要埋設在路面之下,因此會有安裝、維護費用高,造成路面破壞等問題,而采用基于視頻的虛擬線圈的車輛計數方法完全避免了以上問題,且可以針對多個感興趣區域進行檢測。2.虛擬線圈車輛計數法的原理是在采集到的交通流視頻中,在需要進行車輛計數的道路或路段上設置一條或一條以上的檢測線對通過車輛進行檢測,從而完成計數工作。檢測線的設置原則一般是在檢測車道上設置一條垂直于車道線,居中的虛擬線段,通過判斷其與通過車輛的相對位置的變化,完成車流量統計的工作。如下圖所示,綠色的線就是虛擬檢測線: """""" 1.虛擬線圈法檢測的方法是,計算前后兩幀圖像的車輛檢測框的中心點連線,若該連線與檢測線相交,則計數加一,否則計數不變。 2.那怎么判斷兩條線段是否相交呢?假設有兩條線段AB,CD,若AB,CD相交,我們可以確定:1.線段AB與CD相交,即點A和點B分別在線段CD的兩邊;2.線段CD與AB相交,即點C和點D分別在線段AB的兩邊;上面兩個條件同時滿足是兩線段相交的充要條件,所以我們只需要證明點A和點B分別在線段CD的兩邊,點C和點D分別在線段AB的兩邊,這樣便可以證明線段AB與CD相交了。3.在上圖中,線段AB與線段CD相交,于是我們可以得到兩個向量AC、AD,其中C和D分別在AB的兩邊。1.向量AC在向量AB的逆時針方向,得AB×AC > 0。AB×AC實際是以A點為時鐘圓盤的中心點,AB和AC分別是時鐘的兩個時針。向量AC在向量AB的逆時針方向的意思即為時針AB向時針AC進行逆時針移動,也即為B點向C點進行逆時針移動,最終得出AB×AC > 0;2.向量AD在向量AB的順時針方向,得AB×AD < 0。AB×AD實際是以A點為時鐘圓盤的中心點,AB和AD分別是時鐘的兩個時針。向量AD在向量AB的順時針方向的意思即為時針AB向時針AD進行順時針移動,也即為B點向D點進行順時針移動,最終得出AB×AD < 0;最終得出 AB×AC > 0 和 AB×AD < 0 兩個向量叉乘的結果為異號。3.這樣,方法就出來了:如果線段CD的兩個端點C和D,與另一條線段AB中的一個端點(A或B,只能是其中一個)連成的向量(比如AC/AD),然后AC/AD與向量AB做叉乘。若結果異號,表示C和D分別在線段AB的兩邊;若結果同號,則表示CD兩點都在AB的其中一邊,則肯定不相交。所以我們利用叉乘的方法來判斷車輛是否經過檢測線。4.此處的叉乘使用的是兩個向量進行叉乘計算1.向量AB(線段AB):可以是圖像畫面中的檢測線,檢測線的設置原則一般是在檢測車道上設置一條垂直于車道的虛擬線段。2.向量CD(線段CD):可以是前后兩幀的目標框圖像中的中心點所連成的一條線段。3.那么當線段CD中的C、D兩個點(前后兩幀的兩個中心點)分別位于線段AB(檢測線)的兩邊時,那么此時可以通過兩個向量的叉乘計算,得出是否線段CD和線段AB是否相交。 """ # 線與線的碰撞檢測:叉乘的方法判斷兩條線是否相交 # 計算叉乘符號 def ccw(A, B, C):return (C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0]) """ (C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0])1.[0]:線段的其中一點的x坐標[1]:線段的其中一點的y坐標2.A點坐標(x1, y1)、B點坐標(x2, y2)、C點坐標(x3, y3)。A點坐標(x1, y1) 和 B點坐標(x2, y2) 那么得 A×B = x1*y2 - x2*y1。3.BA為(x2-x1, y2-y1),CA為(x3-x1, y3-y1)。CA(x3-x1, y3-y1)中將x3-x1看作是w1,將y3-y1看做是h1;BA(x2-x1, y2-y1)中將x2-x1看作是w2,將y2-y1看做是h2;得出CA為(w1, h1),BA為(w2, h2),那么CA*BA = w1*h2 - w2*h1。4.可以把 (C[1] - A[1]) * (B[0] - A[0]) - (B[1] - A[1]) * (C[0] - A[0]) 轉換為 (C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0]) 來使用,兩者等同。5.BA為(x2-x1, y2-y1),BA還可以看作為(w2, h2)。CA為(x3-x1, y3-y1),CA還可以看作為(w1, h1)。(C[1] - A[1]):y3-y1,也即h1(B[0] - A[0]):x2-x1,也即w2(B[1] - A[1]):y2-y1,也即h2(C[0] - A[0]):x3-x1,也即w16.(C[1] - A[1]) * (B[0] - A[0]) - (B[1] - A[1]) * (C[0] - A[0]) 即可以看做 BA*CA = h1*w2 - h2*w1 7.如果線段CD的兩個端點C和D,與另一條線段AB中的一個端點(A或B,只能是其中一個)連成的向量(比如AC/AD),然后AC/AD與向量AB做叉乘。此處便使用BA*CA做叉乘,根據BA*CA = h1*w2 - h2*w1 得出 (C[1] - A[1]) * (B[0] - A[0]) - (B[1] - A[1]) * (C[0] - A[0])。 """ # 檢測AB和CD兩條直線是否相交 def intersect(A, B, C, D):return ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D) """ CA(x3-x1, y3-y1)中將x3-x1看作是w1,將y3-y1看做是h1 BA(x2-x1, y2-y1)中將x2-x1看作是w2,將y2-y1看做是h2 DA(x4-x1, y4-y1)中將x4-x1看作是w3,將y4-y1看做是h3 CB(x3-x2, y3-y2)中將x3-x2看作是w4,將y3-y2看做是h4 DB(x4-x2, y4-y2)中將x4-x2看作是w5,將y4-y2看做是h5ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D) 1.ccw(A, C, D):(D[1] - A[1]) * (C[0] - A[0]) > (C[1] - A[1]) * (D[0] - A[0]) 即可以看做 CA*DA = h3*w1 - h1*w3 2.ccw(B, C, D):(D[1] - B[1]) * (C[0] - B[0]) > (C[1] - B[1]) * (D[0] - B[0]) 即可以看做 CB*DB = h5*w4 - h4*w5 3.ccw(A, B, C):(C[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (C[0] - A[0]) 即可以看做 BA*CA = h1*w2 - h2*w1 4.ccw(A, B, D):(D[1] - A[1]) * (B[0] - A[0]) > (B[1] - A[1]) * (D[0] - A[0]) 即可以看做 BA*DA = h3*w2 - h2*w3 5.ccw(A, C, D) != ccw(B, C, D):AC×AD < 0 和 BC×BD > 0 兩個向量叉乘的結果為異號。向量AD在向量AC的順時針方向。向量BD在向量BC的逆時針方向。 6.ccw(A, B, C) != ccw(A, B, D):AB×AC > 0 和 AB×AD < 0 兩個向量叉乘的結果為異號。向量AC在向量AB的逆時針方向。向量AD在向量AB的順時針方向。 7.ccw(A, C, D) != ccw(B, C, D) and ccw(A, B, C) != ccw(A, B, D):同時符合上述兩者關系則得到AB和CD相交。 """另外一種叉乘代碼的寫法
# -*- coding: utf-8 -*- def cross_vector(A, B, C):'''求向量 AB x AC 的結果,叉乘'''AB = [B[0]-A[0], B[1]-A[1]]AC = [C[0]-A[0], C[1]-A[1]]return AB[0] * AC[1] - AB[1] * AC[0]def intersection(A, B, C, D):'''A B C D 為四個頂點坐標'''if (cross_vector(A, B, C)*cross_vector(A, B, D)<0) and (cross_vector(C, D, A)*cross_vector(C, D, B)<0):return Trueelse:return False # -*- coding: utf-8 -*- def cross_vector(A, B, C):'''求向量 AB x AC 的結果,叉乘'''AB = [B[0]-A[0], B[1]-A[1]]AC = [C[0]-A[0], C[1]-A[1]]return AB[0] * AC[1] - AB[1] * AC[0]def intersection(A, B, C, D):'''A B C D 為四個頂點坐標'''if (cross_vector(A, B, C)*cross_vector(A, B, D)<0) and (cross_vector(C, D, A)*cross_vector(C, D, B)<0):return Trueelse:return Falseline1=[112, 120, 24, 360] line2=[90, 180, 300, 60] A=line1[:2] B=line1[2:] C=line2[:2] D=line2[2:]print('A:{} B:{} C:{} D:{}'.format(A, B, C, D)) if intersection(A, B, C, D):print('兩線段相交!') else:print('兩線段不相交')總結
以上是生活随笔為你收集整理的叉乘:基于虚拟线圈法的车流量统计的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端学习(1655):前端系列实战课程之
- 下一篇: 【蓝桥杯历年题】2020蓝桥杯A组省赛第