本篇內(nèi)容主要講解“怎么利用Python繪制酷炫的車輛軌跡”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“怎么利用Python繪制酷炫的車輛軌跡”吧!
創(chuàng)新互聯(lián)建站專注于企業(yè)成都營銷網(wǎng)站建設(shè)、網(wǎng)站重做改版、洛隆網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、成都h5網(wǎng)站建設(shè)、成都商城網(wǎng)站開發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為洛隆等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
最近遇到了一類圖,非常好看,并且在其他論文中也多次遇到。比如,在 Trajectory data-based traffic flow studies: A revisit 一文中的圖 1 ,如下圖所示1:
由于原圖較長,這里僅引用了部分圖。從上圖中可以清楚的看出幾個關(guān)鍵信息:
橫軸表示時間變化,說明數(shù)據(jù)需要是時間序列的
縱軸表示空間位置,可以理解為從離開某一道路截面后,車輛行駛的距離
每條軌跡線均表示一輛車的行駛路徑變化,而線條的顏色則表示瞬時速度值
因此,如果想要繪制出上圖,那么就需要有車輛的瞬時軌跡、速度、時間等信息的數(shù)據(jù)集。
為了嘗試?yán)L制出該圖像,現(xiàn)在需要做兩個工作。第一,找到合適的數(shù)據(jù);第二,找到順手的繪圖工具。
對于 NGSIM 數(shù)據(jù)集,作簡要介紹2:其中包含 4 個路段的車輛軌跡數(shù)據(jù),任何一個均是采用在路段的周邊高層建筑上設(shè)置高清攝像機(jī)錄像,然后通過圖像處理,將每輛車的軌跡變化采集出來,進(jìn)而可計算出車輛所在的車道、瞬時速度、瞬時加速度、瞬時車頭時距等等。
作為與本次繪圖相關(guān)的關(guān)鍵信息,我們僅需知道以下數(shù)據(jù):
作為演示,僅使用一個車道的數(shù)據(jù)即可
每輛車從進(jìn)入攝像區(qū)域到離開,中間的瞬時速度信息,NGSIM 中對應(yīng)的數(shù)據(jù)標(biāo)簽是 v_Vel
每輛車從進(jìn)入攝像區(qū)域到離開,中間的位置坐標(biāo)變化,NGSIM 中對應(yīng)的數(shù)據(jù)標(biāo)簽是 Local_X、Local_Y
與之對應(yīng)的時刻,NGSIM 中對應(yīng)的數(shù)據(jù)標(biāo)簽是 Global_Time
好了,知道了上述三個關(guān)鍵數(shù)據(jù)后,就可以利用繪圖工具繪制了。
考慮到可重復(fù)性、可移植性和方便程度,本次采用 Python 中的 Matplotlib 包來繪制
在開始繪圖之前,需要在 Python 環(huán)境中已經(jīng)配置好以下三個包:
Pandas,本文主要作用在于讀取、處理數(shù)據(jù)
Numpy,本文主要用于科學(xué)計算
Matplotlib,本文主要用于繪圖
毫無疑問,這幾個包是會被用到的,因此,我們先在程序中導(dǎo)入它們:
import pandas as pd import numpy as np import matplotlib import matplotlib.pyplot as plt
然后,我們需要將包含時間、位移、速度的數(shù)據(jù)導(dǎo)入 Python 中。這里需要注意,按照常規(guī)思路,我們只需將這三類數(shù)據(jù)賦值給不同變量即可,但本次繪制的圖則不能直接這樣做。
因為,從圖 1 中我們可以看出,該圖是有很多軌跡線組成的,也就是說每輛車都是一組數(shù)據(jù),并且依賴于時間變化,且存在先后順序。
比如,同一車道內(nèi),1 號先進(jìn)入研究區(qū)域,那么它的數(shù)據(jù)則被記錄;隨后,2 號車進(jìn)入研究區(qū)域,同樣被記錄位置變化、瞬時速度、時間。但是,這里的時間是不同的,是逐漸推移的。
一個思路是同時將所有車輛繪制在:X 軸是時間變化,Y 軸是位置變化的圖像中。但是,這個操作需要將每輛車的數(shù)據(jù)均準(zhǔn)備好,這對于同時繪制 300~400 輛車的軌跡圖是不現(xiàn)實的。
為了解決這個問題,一個可行的思路是:循環(huán)繪制每輛車的軌跡隨時間變化。這樣可以只讀取一次數(shù)據(jù),然后依據(jù)車輛 ID 來循環(huán)繪制在同一坐標(biāo)象限內(nèi)。由于每輛車存在先后順序,因此無需擔(dān)心每輛車之間的軌跡重疊。
于是,這一步我們需要做的是:
讀取基礎(chǔ)數(shù)據(jù)集,并篩選出需要使用的某車道數(shù)據(jù),比如車道 3
需要將該車道中所有的車輛 ID 提取出來,并且是依據(jù)時間先后順序排序,也就是根據(jù)數(shù)據(jù)標(biāo)簽 Global_Time 來排序,這個是全局時間
于是,我們可寫出以下代碼(所有代碼可以左右滑動):
# 讀取數(shù)據(jù) data = pd.read_csv(r'F:\NGSIMData.csv') # 提取車道數(shù)據(jù) lanedata = data[data.Lane_ID == 3] # 提取車輛編號 x_vehID = lanedata.drop_duplicates(['Vehicle_ID']) # 依據(jù) Global_Time 按照時間先后順序排序 x_vehID = x_vehID.sort_values(by='Global_Time') # 對排序后的車輛 ID 的索引進(jìn)行重置,方便索引 x_vehID = x_vehID.reset_index(drop = True)
到這里,我們已經(jīng)將某個車道的數(shù)據(jù)提取了出來,并且將其中所有的車輛編號也提取出來了,且按照時間先后順序。此時,僅需要按照前文說的:循環(huán)繪制每輛車的軌跡即可。在開始之前,我們需要先預(yù)設(shè)一下圖的大小,以及字體屬性。
# 導(dǎo)入字體屬性相關(guān)的包或類 from matplotlib.font_manager import FontProperties # 預(yù)設(shè)字體類型、大小 font = FontProperties(fname=r"C:\Windows\Fonts\times.TTF", size=10) #設(shè)置畫布的尺寸 plt.figure(figsize=(10, 4))
接下來就是循環(huán)繪制軌跡圖了。這里有幾個問題需要解釋一下:
既然是循環(huán)繪制,自然就是每次繪制的思路完全一致,具體體現(xiàn)在代碼中
對于單次繪圖,僅需通過第一個車輛 ID 索引對應(yīng)所有的數(shù)據(jù),然后將時間、位移、速度分別賦值給 x、y、v
注意,對于時間,NGSIM 給出的是時間戳格式,需要轉(zhuǎn)換
注意,對于距離和速度,NGSIM 給出的單位是英尺,需要轉(zhuǎn)換
時間將體現(xiàn)在 X 軸,距離將體現(xiàn)在 Y 軸,速度將體現(xiàn)在軌跡線的顏色上
其中,也有一個棘手的問題。那就是,假設(shè)某一車輛進(jìn)入某車道一段時間后,換道至其他車道,隨后過了一段時間,該車輛又換道至當(dāng)前車道。這樣就會出現(xiàn),在時間的前半部分有軌跡線,中間部分沒有軌跡線,后半部分有軌跡線。
對于這種情況,如果我們選擇折線圖繪制,其便會將斷開的部分直接用線段連接起來,這是折線圖的特征。但是,對于這類現(xiàn)象,我們并不期望它們是連接的,也就是沒有軌跡的時間段內(nèi),最好是空白的。
為了解決這個問題,我選擇了散點(diǎn)圖。由于 NGSIM 采集數(shù)據(jù)的頻率是 0.1s,數(shù)據(jù)點(diǎn)非常密集,也就是說對于連續(xù)的軌跡,即便我們用散點(diǎn)圖繪制,出來的效果也是類似于折線的。比如:
注意,右上角是有斷開的區(qū)域的,如果是用折線圖繪制,就不會出現(xiàn)這種應(yīng)該出現(xiàn)的效果。
另一個問題是顏色的處理,也就是需要將每輛車的速度值對應(yīng)到同一時刻的軌跡點(diǎn)上。而這一點(diǎn),散點(diǎn)圖中可以將散點(diǎn)的顏色映射給數(shù)值,也就是我們需要的,具體就是代碼中的 c=v,但這個命令僅是將速度值映射給顏色。
如果要將某一顏色主題應(yīng)用于軌跡圖中,那么就需要做兩個工作:
定義顏色主題,也就是散點(diǎn)圖中的命令 cmap='jet_r'
因為后邊我們需要設(shè)置顏色條圖例,所以需要將顏色條中的顏色數(shù)值與軌跡圖中的顏色歸一化,讓其一一對應(yīng)。
我們給出這一循環(huán)繪制軌跡-速度圖的代碼:
i = 0 while i < (len(x_vehID)-1): # 循環(huán)繪制軌跡圖 cardata = lanedata[lanedata.Vehicle_ID == x_vehID[i]] # 將時間賦值給變量 x x = cardata['Global_Time'] # 計算相對移動距離,并賦值給變量 y y = np.sqrt(np.square(cardata['Local_Y']) + np.square(cardata['Local_X']) ) # 將速度賦值給變量 v,同時定義速度為顏色映射 v = cardata['v_Vel'] #設(shè)定每個圖的colormap和colorbar所表示范圍是一樣的,即歸一化 norm = matplotlib.colors.Normalize(vmin=0, vmax=25) # 繪制散點(diǎn)圖 ax = plt.scatter(x,y, marker = '.', s=1, c=v, cmap='jet_r', norm = norm) print(i) i = i + 1
其中,我們對 y 值求了平方和的開方,也就是根據(jù)車輛的橫縱坐標(biāo)計算位移。我們還將繪制的散點(diǎn)圖 ax = plt.scatter 賦給了 ax ,方便后邊對散點(diǎn)圖的屬性進(jìn)行設(shè)置。
這里需要注意的是,對于散點(diǎn)的繪制,我們利用循環(huán)解決。而對于坐標(biāo)軸等的設(shè)置,只需設(shè)置一次,無需循環(huán)。到這里,我們可以得到一個不完美的軌跡-速度圖:
不知為何,初步繪制出來的圖的兩側(cè)存在大量的空缺,猜測可能是由于我在數(shù)據(jù)篩選階段出了問題,又或者這些本就沒有數(shù)據(jù)點(diǎn)。無論怎樣,這樣不影響我們來學(xué)習(xí)繪制該類圖像。
此時,需要再給上圖加一個顏色條圖例,以表示不同顏色對應(yīng)的速度數(shù)值,這里只需要兩行代碼搞定:
# 添加顏色條 plt.clim(0, 25) plt.colorbar()
即可得到如下所示的圖像,圖中修改了一下顏色主題:
這里需要注意在循環(huán)繪圖的代碼內(nèi)部的一行代碼:
# 設(shè)定每個圖的colormap和colorbar所表示范圍是一樣的,即歸一化 norm = matplotlib.colors.Normalize(vmin=0, vmax=25)
該行代碼決定了顏色條圖例中的顏色和左邊軌跡圖中的顏色是一致的,也就是必須按照顏色條設(shè)定的色階來繪制軌跡和呈現(xiàn)色彩。
如果沒有該行代碼,就算添加了顏色條的代碼,繪制出來的顏色條和左邊的軌跡圖也不對應(yīng),大家可以試試看~
這個操作就比較常規(guī)了,根據(jù)自己需要添加即可,常規(guī)的代碼隨便網(wǎng)上搜一個就有,包括刻度值得設(shè)置等等。
這一步僅重點(diǎn)說明一點(diǎn):就是 X 軸繪制時利用的是時間戳數(shù)據(jù),由于數(shù)值太密集,所以圖中我關(guān)掉了 X 軸的刻度值。如果想要顯示如圖 1 所示的時間格式,一個可行的辦法是向圖像中添加文字。
也就是說,手動將時間放置在想要防止的刻度下,我們先看一組代碼:
# 設(shè)置 X 坐標(biāo)軸刻度 plt.text(x, y, '8:05', fontproperties=font2) plt.text(x, y, '8:10', fontproperties=font2) plt.text(x, y, '8:15', fontproperties=font2) plt.text(x, y, '8:20', fontproperties=font2)
通過這組代碼,我們便可以將制定的時間放置在圖中指定的位置,基于坐標(biāo)(x,y)。
最后,附上一個個人認(rèn)為比較完美的圖像,供大家參考:
將坐標(biāo)軸設(shè)置為漢字,是因為漢字與英文同時出現(xiàn)時比較難處理,大家可以嘗試調(diào)一下。
到此,相信大家對“怎么利用Python繪制酷炫的車輛軌跡”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!