Cityscapes踩坑記錄


Cityscapes是做像素級分割一個很常用的數據集,我因為需要確認論文的代碼復現效果下載了這個數據集。這個數據集看上去好像就是個輸入圖像和標簽的pair,實際上坑很多,下面簡單總結下吧。

在閱讀之前,希望你已經看過了這篇帖子:https://blog.csdn.net/zz2230633069/article/details/84591532,因為對於數據集的文件組織結構下面將不會涉及。然后希望你也能知道除了官網(https://www.cityscapes-dataset.com/)下載的數據集外,還有一個Github工具包(https://github.com/mcordts/cityscapesScripts)最好也下載下來,這其中包含了preparation文件夾下可以幫助你生成*_labelTrainId.png的19類別標注的腳本。

 

下面是正文:

1. 數據集沒有測試集,只有驗證集。想得到測試結果需要提交模型在線測試。

2. 這個數據集直接下載下來的話,輸入就是leftImage8bit里面的文件,然后需要注意的是其對應的標注是有幾類的,包括彩色的*_color.png和按照類別標注的*_labelIds.png等等。這個*_labelIds.png實際上是完整的34類標注,像素按照類別被標成-1~33中的數字(不過我用opencv讀進來發現標注是從1~33的,-1當然沒有但0不知道為何也消失了,這一問題在讀取labelTrainId時沒有出現),便於訓練時直接使用交叉熵損失函數。在那個github工具包中有提供將1-34對應轉換成*_color.png的腳本,可在可視化時使用。

3. 在github工具包的helper/labels.py下面有類別和id信息的一一對應,可以看到很多論文中使用的其實是19類的trainId,所以我們還需要通過工具包中preparation文件夾中的腳本額外生成*_labelTrainIds.png

 

 4. 特別提醒下,因為原圖2048*1024實在太大,一般讀取都會做resize,在resize輸入時可以就用默認的雙線性插值,但在resize標簽的時候記得得用最近鄰插值,要不然會多出一些其他數字的。

5. trainId生成后,需要注意的是無關的類別都被標注成了255,所有使用交叉熵損失函數時記得加上ignore_index=255

6. 關於mIoU的計算,工具包中提供了34類的訓練模型的計算,我因為需要復現的是19類的所以自己寫了一個,就是直接算交集並集然后除一下嘛,結果測出來結果差的要命。上網搜了一圈扒了開源代碼的一個類下來:

import numpy as np


class Evaluator(object):
    def __init__(self, num_class):
        self.num_class = num_class
        self.confusion_matrix = np.zeros((self.num_class,)*2)

    def Pixel_Accuracy(self):
        Acc = np.diag(self.confusion_matrix).sum() / self.confusion_matrix.sum()
        return Acc

    def Pixel_Accuracy_Class(self):
        Acc = np.diag(self.confusion_matrix) / self.confusion_matrix.sum(axis=1)
        Acc = np.nanmean(Acc)
        return Acc

    def Mean_Intersection_over_Union(self):
        MIoU = np.diag(self.confusion_matrix) / (
                    np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) -
                    np.diag(self.confusion_matrix))
        MIoU = np.nanmean(MIoU)
        return MIoU

    def Frequency_Weighted_Intersection_over_Union(self):
        freq = np.sum(self.confusion_matrix, axis=1) / np.sum(self.confusion_matrix)
        iu = np.diag(self.confusion_matrix) / (
                    np.sum(self.confusion_matrix, axis=1) + np.sum(self.confusion_matrix, axis=0) -
                    np.diag(self.confusion_matrix))

        FWIoU = (freq[freq > 0] * iu[freq > 0]).sum()
        return FWIoU

    def _generate_matrix(self, gt_image, pre_image):
        mask = (gt_image >= 0) & (gt_image < self.num_class)
        label = self.num_class * gt_image[mask].astype('int') + pre_image[mask]
        count = np.bincount(label, minlength=self.num_class**2)
        confusion_matrix = count.reshape(self.num_class, self.num_class)
        return confusion_matrix

    def add_batch(self, gt_image, pre_image):
        assert gt_image.shape == pre_image.shape
        self.confusion_matrix += self._generate_matrix(gt_image, pre_image)

    def reset(self):
        self.confusion_matrix = np.zeros((self.num_class,) * 2)

這個是通過混淆矩陣計算的,然后通過add_batch加入新的預測、GT對后就可以調用Mean_Intersection_over_Union()函數獲取新的mIoU

7. 我在512*256的輸入下,不做任何增廣、crop等等操作,使用deeplab v3+、adam和學習率0.99指數下降,訓練大概200個epoch只能到0.47的mIoU,不知道是不是有什么地方搞錯了。使用開源的deeplab v3+在512*512的crop上直接跑大概能有0.65,雖說輸入大小不一樣lr什么的策略也都不一樣,但相比之下還是差太多了點。

 

供大家參考。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM