天天看點

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

作者:小蘇不秃頭

對Nuscenes資料集一無所知???手把手帶你玩轉Nuscences資料集

嗯,實話實說,标題可能寫的有點誇張怎麼說是誇張呢,因為玩轉Nuscenes資料集也是我的目标本文将從一個初學者的角度來認識Nuscenes資料集,首先會對Nuscenes資料集的結構進行分析,然後會通過代碼教大家如何擷取Nuscenes資料集中的各種資料【由于自己也是剛剛接觸,可能有的地方描述的不夠完整不夠準确,但是我會對我學習中的一些比較迷惑的地方重點講解,可能會和開始學習Nuscenes的讀者産生共鳴,當然随着我的後續學習,我也會不斷的更新内容,讓我們一起真正的玩轉Nusences資料集】

Nuscenes資料集簡介

先來簡單的介紹一下Nuscenes資料集,相信大家對Nuscenes資料集應該是有一些了解的,至少應該知道這是和自動駕駛相關的,知道這些就足夠了,下面再來補充一些知識Nuscenes資料的采集來自不同城市的1000個場景中,采集車上配備了完善的傳感器,包括6個相機(CAM)、1個雷射雷達(LIDAR)、5個毫米波雷達(RADAR)、IMU和GPS。傳感器在采集車上的布置如下圖所示:

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

可以看出,相機(CAM)有六個,分别分布在前方(Front)、右前方(Front Right)、左前方(Front Left)、後方(Back)、右後方(Back Right)、左後方(Back Left);雷射雷達(LIDAR)有1個,放置在車頂(TOP);毫米波雷達有五個,分别放置在前方(Front)、右前方(Front Right)、左前方(Front Left)、右後方(Back Right)、左後方(Back Left)。

準備工作✨✨✨

資料才是王道,第一步我們當然是需要下載下傳資料了。Nuscenes的官網下載下傳連結如下:https://www.nuscenes.org/download。第一次下載下傳應該是需要進行登入的,登入完成就可以進行下載下傳啦!!!登入完成你可能會發現有太多可下載下傳的資源了,我該下載下傳哪一個呢,這裡我們用做實驗,故不需要下載下傳完整的資料集,下載下傳mini版本即可【完整的太大了,mini大約4個G】。

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

下載下傳完成進行解壓後,應該有如下的檔案結構:

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

接下來我們對上圖中的4個檔案進行分析:

  • maps檔案夾
  • 打開map檔案夾,可以看到4個地圖的圖檔,這種圖檔資訊的檔案我們很容易了解,這裡不過多叙述。
  • samples檔案夾
  • 打開samples檔案夾,出現了這樣的目錄結構:不知道大家能不能看出來這些是什麼,對于英語不好的我來說,打開檔案夾出現一堆這種大寫的英文着實反應不過來。好吧,不賣關子了其實這裡就是上文提到的傳感器(6個相機、1個雷射雷達、5個毫米波雷達)所采集到的資訊。不信你可以打開6個相機所對應的檔案夾,你可以發現裡面都是采集到的圖檔,至于雷射雷達和毫米波雷達所對應的檔案夾裡也存儲着各自采集的資訊,隻是格式不能像圖檔那樣直接進行檢視。
  • sweeps檔案夾
  • 打開sweeps檔案夾,你會發現其結構和samples檔案夾是完全一樣的。那麼samples檔案夾和sweeps檔案夾有什麼差別呢?可以這樣了解,samples檔案夾中存儲的資訊是較為關鍵、重要的,而sweeps檔案夾中的資訊則相對次要。
  • v1.0-mini檔案夾
  • 打開v1.0-mini檔案夾,或許你又懵了,裡面是一堆json格式的檔案。
  • 這些json檔案是幹什麼的呢,我們嘗試打開一個看看裡面的内容(這裡打開的是category.json)。首先提示一下category是種類的意思,那麼這個josn檔案中就存儲了一些關于目标對象屬于哪一類的資訊,如下圖紅框框住部分,表示目标對象是一個adult。【圖中的種類顯示的是human.pedestrian.adult,表示一種所屬關系,即adult屬于pedestrian,pedestrian屬于human】

資料讀取✨✨✨

安裝庫

首先需要按照nuscenes-devkit庫,使用pip安裝即可。【注意:後文的代碼我都是在jupyter notebook上運作的,若用其他軟體運作,代碼可能需要略微進行改變】

pip install nuscenes-devkit           

導入相關子產品和資料集

這裡的dataroot為下載下傳的mini資料集的路徑,運作成功後應出現如下的資訊:

%matplotlib inline
 from nuscenes.nuscenes import NuScenes
 nusc = NuScenes(version='v1.0-mini', dataroot='E:\\毫米波雷達\\v1.0-mini', verbose=True)           
對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

看到上圖紅框中的内容不知大家是否有種似曾相似的感覺,沒錯就是之前v1.0-mini檔案夾中的那些檔案。下面對這些名詞進行解釋,英文為官方給出的解釋,中文為自己總結的。

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集
對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

看來上圖中各名詞的解釋,估計還是比較迷惑的,下面會對這些内容進行逐一的解釋

場景scene⭐⭐⭐

使用nusc.list_scenes()可以檢視資料中的所有場景。

nusc.list_scenes()           

輸出結果 : mini資料集中隻包含10個場景,每個場景大約持續20s【有的19s】,即每個場景有20秒采集到的資訊。

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

可以使用下列指令來檢視某個場景中的資訊:

my_scene = nusc.scene[0]
 my_scene           

輸出結果 :token為唯一辨別,通過token可以擷取對應資訊。

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

樣本sample⭐⭐⭐

先來說說sample和scene的關系,前面說到,每個scene大約持續20s,那sample就是每0.5秒進行一次采樣。也可以這樣了解sample和scene,sence相當于20s的視訊,sample就是每0.5s取一幀的圖像。

上文已經得到了某個場景的資訊【scene-0061】,現可以通過my_scene得到某一個sample的token值。

first_sample_token = my_scene['first_sample_token']  #擷取第一個sample的token值
 first_sample_token            

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

當我們得到第一個sample的token值後,我們可以通過 nusc.get指令來擷取目前sample的資訊:

my_sample = nusc.get('sample', first_sample_token)
 my_sample           

輸出結果 :結果中包含了傳感器采集到的資訊、标注資訊等等。

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

樣本資料 sample_data⭐⭐⭐

使用my_sample['data']可以擷取sample的資料sample_data。

my_sample['data']           

輸出結果 :這些傳感器裡包含了許多的樣本資料。

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

我們可以使用下列指令來将這些傳感器中采集的進行可視化:

sensor_radar = 'RADAR_FRONT'  #這裡選擇的傳感器為前方的毫米波雷達傳感器
 radar_front_data = nusc.get('sample_data',my_sample['data'][sensor_radar])  
 radar_front_data           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集
nusc.render_sample_data(radar_front_data['token'])           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

這裡隻展示了RADAR_FRONT,即前方毫米波雷達傳感器的可視化結果,可視化其他傳感器的方法和上文一緻。

樣本标注 sample_annotation⭐⭐⭐

上文提到my_sample中包含了傳感器采集到的資訊、标注資訊,在sample_data中已經展示了傳感器采集到的資訊,這一部分将展示樣本标注的資訊,方法與之前是類似的。

my_annotation_token = my_sample['anns'][18]
my_annotation_metadata = nusc.get('sample_annotation',my_annotation_token)
my_annotation_metadata           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集
nusc.render_annotation(my_annotation_metadata['token'])           
對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

執行個體 instance

通過nusc.instance可以擷取執行個體:

my_instance = nusc.instance[0]
my_instance           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

我們也可以可視化這個執行個體:

instance_token = my_instance['token']
nusc.render_instance(instance_token)           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

類别categories

通過nusc.list_categories可以擷取類别:

nusc.list_categories()           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

nusc.category[i]表示擷取第i個類别的資訊:

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

屬性attributes⭐⭐⭐

通過nusc.list_attributes可以擷取屬性:

nusc.list_attributes()           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

屬性在一個場景中是可以變換的,下列代碼展示了行人從移動到站立,屬性發生了變換。【注意:這部分代碼直接看可能不是很好了解,将代碼一部分一部分的運作,看看每步的結果,你就會恍然大悟】

my_instance = nusc.instance[27]
first_token = my_instance['first_annotation_token']
last_token = my_instance['last_annotation_token']
nbr_samples = my_instance['nbr_annotations']
current_token = first_token

i = 0
found_change = False
while current_token != last_token:
    current_ann = nusc.get('sample_annotation', current_token)
    current_attr = nusc.get('attribute', current_ann['attribute_tokens'][0])['name']
    
    if i == 0:
        pass
    elif current_attr != last_attr:
        print("Changed from `{}` to `{}` at timestamp {} out of {} annotated timestamps".format(last_attr, current_attr, i, nbr_samples))
        found_change = True

    next_token = current_ann['next']
    current_token = next_token
    last_attr = current_attr
    i += 1
           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

可視化 visibility

可視化在前文中其實已經講過了,這裡再看看代碼加深印象。

anntoken = my_sample['anns'][9]
visibility_token = nusc.get('sample_annotation', anntoken)['visibility_token']
print("Visibility: {}".format(nusc.get('visibility', visibility_token)))
nusc.render_annotation(anntoken)           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

傳感器 sensor

傳感器前文其實也或多或少的講過了,可以通過nusc.sensor來檢視傳感器,部分結果如下:

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

因sample_data中就存儲着傳感器的資訊,是以可以通過nusc.sample_data[i]來擷取傳感器的資訊,結果如下:

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

校準傳感器 calibrated_sensor

通過下列指令來得到某傳感器的校準資訊:

sensor_token = nusc.calibrated_sensor[0]
sensor_token           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

車輛姿态 ego_pose

nusc.ego_pose[0]           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

日志 log

nusc.log[0]           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

地圖 map

nusc.map[0]           

輸出結果 :

對Nuscenes資料集一無所知,手把手帶你玩轉Nuscenes資料集

總結

最後了,說點什麼呢,上面這些東西你看是很難看明白的,自己動手多敲一敲,哪裡不明白敲敲代碼看看輸出的結果,好記性不如爛筆頭,加油各位

這部分官方是給了參考的代碼的,可以再Google colab上直接運作,這裡給出官方的連結:https://colab.research.google.com/github/nutonomy/nuscenes-devkit/blob/master/python-sdk/tutorials/nuscenes_tutorial.ipynb#scrollTo=x1Niizx-rsKm,但是我想大家還是自己敲一敲會印象更加深刻

繼續閱讀