天天看點

YOLOv1-從零到落地

雖然網上有很多YOLO 相關的文章,但是如果要用YOLO直接做一個落地産品,卻沒有一篇文章可以對每個步驟都進行指導了,為此,本文根據自己的項目經驗,結合論文的精度和網絡的相關文章,總結一篇可以從零到落地的文章。如有不詳細或者遺漏的請在評論區留言,謝謝。

原始論文路徑:pdf路徑

講解比較好的文章:YOLO文章詳細解讀

1,資料标注

1,推薦使用LabelImg,支援輸出YOLO輸出格式,安裝教程和使用說明見連結

2,醫學圖像檢測框标注工具可以采用3D slice,使用教程見連結

資料标注的存儲格式如下:

dog.jpg 104 237 316 527 1 122 117 609 491 2 457 60 694 174 3

其中dog.jpg為圖像的路徑,接着每5個值為一個金标準框(x1,y1,x2,y2,類别)

2,DataSet:定義網絡輸入和loss的金标準輸入

這裡輸入的是歸一化之後并resize為固定大小[448,448]的圖像;

輸出為7x7x30的張量,是以這的标注資料格式需要做一個轉換,轉換為7x7x30的格式,一個參考代碼如下:

h, w, _ = img.shape
grid_size = 7
stride = 1/grid_size
target = torch.zeros([grid_size, grid_size, 30])
boxes = boxes / torch.tensor([w, h, w, h]) # 歸一化到0-1
wh = boxes[:, 2:] - boxes[:, :2]
cxcy = (boxes[:, 2:] + boxes[:, :2])/2
for i in range(cxcy.size(0)):
    center = cxcy[i]
    ij = (center * grid_size).floor()
    delta_xy = (center - ij * stride) * grid_size
    target[int(ij[1]), int(ij[0]), 2:4] = wh[i]
    target[int(ij[1]), int(ij[0]), 7:9] = wh[i]
    target[int(ij[1]), int(ij[0]), :2] = delta_xy
    target[int(ij[1]), int(ij[0]), 5:7] = delta_xy
    target[int(ij[1]), int(ij[0]), 4] = 1
    target[int(ij[1]), int(ij[0]), 9] = 1
    target[int(ij[1]), int(ij[0]), 9+int(label[i])] = 1
           

3,編寫網絡結構

YOLOv1-從零到落地

1,一種方法是實作論文的網絡結構,并書寫轉換接口,把原文的網絡參數加載到自己實作的網絡中,作為預訓練的參數。

2,一種方法是修改目前主流的網絡結構,如VGG16、U-Net、ResNet等,把最後幾層網絡進行修改,隻要確定最後一層網絡的輸出為7x7x30就行。

4,編寫Loss計算子產品

YOLOv1-從零到落地

loss的輸入為predict和target,二者的尺寸都是7x7x30,一個loss類的架構如下:

class Loss(nn.Module):
    def __init__(self):
        super(Loss, self).__init__()

        self.coord = 5.0
        self.noobj = 0.5

    def forward(self, pred, target):
        '''

        :param pred: Bx7x7x30 -inf, inf
        :param target: Bx7x7x30 -inf, inf
        :return:
        '''

        # xy loss
        # wh loss
        # iou loss
        # label loss
           

5,訓練網絡結構

訓練網絡結構的步驟包括如下幾個:

1,執行個體化net = YOLO

2,網絡參數初始化

3,執行個體化Loss

4,執行個體化優化器

5,封裝dataset

6,循環更新網絡參數

6,模型的inference

7,工程化模型

繼續閱讀