目標檢測之二:多尺度

https://zhuanlan.zhihu.com/p/102817180

Multi-scale Training/Testing 多尺度訓練/測試

可參考:

初識CV:MMDetection中文文檔—4.技術細節​zhuanlan.zhihu.com圖標

輸入圖片的尺寸對檢測模型的性能影響相當明顯,事實上,多尺度是提升精度最明顯的技巧之一。在基礎網絡部分常常會生成比原圖小數十倍的特徵圖,導致小物體的特徵描述不容易被檢測網絡捕捉。通過輸入更大、更多尺寸的圖片進行訓練,能夠在一定程度上提高檢測模型對物體大小的魯棒性僅在測試階段引入多尺度,也可享受大尺寸和多尺寸帶來的增益。

multi-scale training/testing最早見於[1],訓練時,預先定義幾個固定的尺度,每個epoch隨機選擇一個尺度進行訓練。測試時,生成幾個不同尺度的feature map,對每個Region Proposal,在不同的feature map上也有不同的尺度,我們選擇最接近某一固定尺寸(即檢測頭部的輸入尺寸)的Region Proposal作爲後續的輸入。在[2]中,選擇單一尺度的方式被Maxout(element-wise max,逐元素取最大)取代:隨機選兩個相鄰尺度,經過Pooling後使用Maxout進行合併,如下圖所示。

使用Maxout合併feature vector

近期的工作如FPN等已經嘗試在不同尺度的特徵圖上進行檢測,但多尺度訓練/測試仍作爲一種提升性能的有效技巧被應用在MS COCO等比賽中。

問題:多尺度的選擇有什麼規則和技巧嗎?

答:如果模型不考慮時間開銷,尺寸往大的開。一般來說尺度越大效果越好,主要是因爲檢測的小目標越多效果越差。如果是新手那就按照默認參數的比例擴大就行了,然後測試的時候取訓練集的中間值。比如cascade50默認尺度是(1333,800),多尺度可以按照默認尺度的倍數擴大比如擴大兩倍(2666,1600),多尺度訓練可以寫成[(1333, 800), (2666, 1600)],單尺度測試可以選擇(2000, 1200),多尺度測試可以選擇爲多尺度訓練的尺度加上他們的中間值[(1333, 800), (2000, 1200),(2666, 1600)]。keep_ratio=True,一般不考慮長邊。

MMDetection中,多尺度訓練/測試:(源碼解析)

只需要修改train_pipeline 和test_pipeline中的img_scale部分即可(換成[(), ()]或者[(), (), ().....])。帶來的影響是:train達到擬合的時間增加、test的時間增加,一旦test的時間增加一定會影響比賽的分數,因爲比賽都會將測試的時間作爲評分標準之一:

參數解析:

  • train_pipelinedict(type='Resize', img_scale=(1333, 800), keep_ratio=True)keep_ratio解析。假設原始圖像大小爲(1500, 1000),ratio=長邊/短邊 = 1.5。
    • keep_ratio=True時,img_scale的多尺度最多爲兩個。假設多尺度爲[(2000, 1200), (1333, 800)],則代表的含義爲:首先將圖像的短邊固定到800到1200範圍中的某一個數值假設爲1100,那麼對應的長邊應該是短邊的ratio=1.5倍爲 [公式] ,且長邊的取值在1333到2000的範圍之內。如果大於2000按照2000計算,小於1300按照1300計算。
    • keep_ratio=False時,img_scale的多尺度可以爲任意多個。假設多尺度爲[(2000, 1200), (1666, 1000),(1333, 800)],則代表的含義爲:隨機從三個尺度中選取一個作爲圖像的尺寸進行訓練。
  • test_pipeline 中img_scale的尺度可以爲任意多個,含義爲對測試集進行多尺度測試(可以理解爲TTA)。
train_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(type='LoadAnnotations', with_bbox=True),
    dict(type='Resize', img_scale=(1333, 800), keep_ratio=True), #這裏可以更換多尺度[(),()]
    dict(type='RandomFlip', flip_ratio=0.5),
    dict(type='Normalize', **img_norm_cfg),
    dict(type='Pad', size_divisor=32),
    dict(type='DefaultFormatBundle'),
    dict(type='Collect', keys=['img', 'gt_bboxes', 'gt_labels']),
]
test_pipeline = [
    dict(type='LoadImageFromFile'),
    dict(
        type='MultiScaleFlipAug',
        img_scale=(1333, 800), #這裏可以更換多尺度[(),()]
        flip=False,
        transforms=[
            dict(type='Resize', keep_ratio=True),
            dict(type='RandomFlip'),
            dict(type='Normalize', **img_norm_cfg),
            dict(type='Pad', size_divisor=32),
            dict(type='ImageToTensor', keys=['img']),
            dict(type='Collect', keys=['img']),
        ])
]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章