YOLOv3學習筆記之資料處理

baidu_huihui發表於2020-12-12

YOLOv3學習筆記之資料處理

目錄

 

dataset中的資料處理

1. 圖片處理

將讀取的圖片進行reshape,變為正方形

def pad_to_square(img, pad_value):
    c, h, w = img.shape
    dim_diff = np.abs(h - w)
    # (upper / left) padding and (lower / right) padding
    pad1, pad2 = dim_diff // 2, dim_diff - dim_diff // 2
    # Determine padding
    pad = (0, 0, pad1, pad2) if h <= w else (pad1, pad2, 0, 0)
    #(左填充,右填充,上填充,下填充)
    # Add padding
    img = F.pad(img, pad, "constant", value=pad_value)

    return img, pad

圖片變為正方形

2. 標籤處理

  1. labels中txt檔案標籤資料的來源。在json檔案中給出的是原始圖片的左上角座標和寬高,但是在下載的labels資料夾中的txt檔案,標籤是已經被處理過了,可以看下面對比圖。
    在這裡插入圖片描述

處理方式如下:

  • json中得到的值box左上角座標(w,y),box寬高w,h,原圖寬高w_factor,h_factor
  • 將左上角座標變為中心點座標(x1,y1)
  • 將中心點座標,寬高等比例縮放,即得到一個相對值(x2,y2,w2,h2)

標籤label的處理方式:

在這裡插入圖片描述

另外還有使用打標工具labelImg得到的資料也是同樣的處理方式,程式碼驗證如下:

import cv2
import numpy as np

img_path='F:/labelimg_test/COCO_train2014_000000000036.jpg'
label_path='F:/labelimg_test/COCO_train2014_000000000036.txt'

image = cv2.imread(img_path)
print(image.shape) #(576, 704, 3) (H,W,C)
h_factor, w_factor = image.shape[:2]
print('原始影像尺寸h:',h_factor,'w:',w_factor)

boxes =np.loadtxt(label_path).reshape(-1,5)

for i in boxes:
    print('label中的標籤:',)
    print('x_label:', i[1],'y_label:', i[2],'w_label:', i[3],'h_label:', i[4])

    x,y,w,h=i[1],i[2],i[3],i[4]
    x=x*w_factor
    y=y*h_factor
    w=w*w_factor
    h=h*h_factor

    x=x-w/2
    y=y-h/2

    print('試著將label中標籤還原到原圖上:')
    print('x:', x,'y: ', y,'w:', w,'h:', h)
    print('\n')

    #左上角座標(下,y),右下角座標(x+w,y+h)
    draw_1=cv2.rectangle(image, (int(x),int(y)), (int(x+w),int(y+h)), color=(0,255,0),thickness=2, lineType=8)

cv2.imwrite("vertical_flip.jpg", draw_1)  #將畫過矩形框的圖片儲存到當前資料夾
cv2.imshow("draw_0", draw_1)  #顯示畫過矩形框的圖片
cv2.waitKey(0)
cv2.destroyWindow("draw_0")

在這裡插入圖片描述

  1. 在dataset中label的處理
  • 將label中的標籤(boxes[1],boxes[2],boxes[3],boxes[4])還原得到真實圖片上的標籤,即左上角座標和寬高
  • 找到右下腳座標,即得到(x1,y1,x2,y2)
  • 原圖片經過填充後,相當於圖片的座標系發生了變化,因此呢,標註框也需要同樣的填充,保證相對位置不變
  • 最後再經過上文提到的標籤變換方法,得到中心點座標和寬高,再除以填充後的寬高padded_w,padded_h,得到相對值
# Extract coordinates for unpadded + unscaled image
            x1 = w_factor * (boxes[:, 1] - boxes[:, 3] / 2)
            y1 = h_factor * (boxes[:, 2] - boxes[:, 4] / 2)
            x2 = w_factor * (boxes[:, 1] + boxes[:, 3] / 2)
            y2 = h_factor * (boxes[:, 2] + boxes[:, 4] / 2)

            # Adjust for added padding
            x1 += pad[0]
            y1 += pad[2]
            x2 += pad[1]
            y2 += pad[3]

            # Returns (x, y, w, h)
            boxes[:, 1] = ((x1 + x2) / 2) / padded_w
            boxes[:, 2] = ((y1 + y2) / 2) / padded_h
            boxes[:, 3] *= w_factor / padded_w
            boxes[:, 4] *= h_factor / padded_h
  1. 對於一個batch資料而言,不同圖片的label都是連線在一起的,因此需要再每一個box資料前新增一個index,用來表示該box屬於batch[index]圖片的,該功能是在自定義的collate_fn(self, batch)函式中實現
  • 給每一個box框新增索引
  • 多尺度訓練,在同一個batch中圖片大小要一致,需要將圖片進行resize到相同的尺寸,在resize時,每10個batch進行一次多尺度訓練,在[min=416-3x32,max=416+3x32]之間隨機選擇一個目標尺寸值
  • 將圖片,標籤以及路徑連線起來,最後返回
    paths=[path0,path1,…]
    imgs=[batch_size,3,w,h]
    targets=[N,6]
  • 預設的collate_fn最後返回的是用棧存起來的,自定義collate返回的使用列表存起來的
    def collate_fn(self, batch):
        """
        :param batch: list 一個批次的資料 [(path,img,target),(),...]
        targets :tuple(target0,target1,...)
        :return:
        """
        paths, imgs, targets = list(zip(*batch)) #*表示以元組形式接收引數  zip打包為元組的列表
       
        # Remove empty placeholder targets
        targets = [boxes for boxes in targets if boxes is not None]
        # Add sample index to targets
        for i, boxes in enumerate(targets):
            boxes[:, 0] = i
        targets = torch.cat(targets, 0)
        # print('拼接後的targets:',targets.shape)

        # Selects new image size every tenth batch
        if self.multiscale and self.batch_count % 10 == 0:
            self.img_size = random.choice(range(self.min_size, self.max_size + 1, 32))
        # Resize images to input shape
        imgs = torch.stack([resize(img, self.img_size) for img in imgs])
        self.batch_count += 1
        return paths, imgs, targets

  1. 再經過dataloader將dataset資料進行包裝,輸入到模型中。

相關文章