faster-rcnn 之 基於roidb get_minibatch(資料準備操作)
阿新 • • 發佈:2019-01-05
【說明】:歡迎加入:faster-rcnn 交流群 238138700,這個函式,輸入是roidb,根據roidb中給出的圖片的資訊,讀取圖片的原始檔,然後整理成blobs,供給網路訓練使用;
def get_minibatch(roidb, num_classes):
這個函式會根據roidb中的資訊,呼叫opencv讀取圖片,整理成blobs返回,所以這個函式是faster-rcnn實際的資料準備操作,我們來分析minibatch.py這個檔案;
【輸入】:roidb是一個list,list中的每個元素是一個字典,每個字典對應一張圖片的資訊,其中的主要資訊有:
boxes:該圖片所有的box的4個座標位置
gt_class:每個boxes對應的類別
gt_overlaps
height:圖片原始的高
width:圖片原始的寬
image:圖片的路徑
seg_areas
【函式解析】:
def get_minibatch(roidb, num_classes): """Given a roidb, construct a minibatch sampled from it.""" num_images = len(roidb)#roidb中元素的個數,就是要處理的圖片的個數 # Sample random scales to use for each image in this batch random_scale_inds = npr.randint(0, high=len(cfg.TRAIN.SCALES), size=num_images)#根據scales的數量,為每張圖片生成一個scales的索引 assert(cfg.TRAIN.BATCH_SIZE % num_images == 0), \ 'num_images ({}) must divide BATCH_SIZE ({})'. \ format(num_images, cfg.TRAIN.BATCH_SIZE)#斷言,要求batchsize必須是圖片數量的整數倍 rois_per_image = cfg.TRAIN.BATCH_SIZE / num_images #計算平均從每個圖片上要產生多少個roi輸入 fg_rois_per_image = np.round(cfg.TRAIN.FG_FRACTION * rois_per_image) #按比率計算每張圖片的roi中需要多少個前景 # Get the input image blob, formatted for caffe im_blob, im_scales = _get_image_blob(roidb, random_scale_inds)#呼叫函式,讀取圖片資料,返回矩陣資料和每張圖片的尺寸縮放資訊 blobs = {'data': im_blob}#把blobs字典的key:data賦值為im_blob,也就是圖片的矩陣資料 if cfg.TRAIN.HAS_RPN:#這裡是針對RPN網路的訓練過程的 assert len(im_scales) == 1, "Single batch only" assert len(roidb) == 1, "Single batch only" # gt boxes: (x1, y1, x2, y2, cls)#gt_boxes每一行對應一個box資訊,包括4個座標和一個類別 gt_inds = np.where(roidb[0]['gt_classes'] != 0)[0] gt_boxes = np.empty((len(gt_inds), 5), dtype=np.float32) gt_boxes[:, 0:4] = roidb[0]['boxes'][gt_inds, :] * im_scales[0] gt_boxes[:, 4] = roidb[0]['gt_classes'][gt_inds] blobs['gt_boxes'] = gt_boxes blobs['im_info'] = np.array( [[im_blob.shape[2], im_blob.shape[3], im_scales[0]]], dtype=np.float32)#影象資訊就是rezise後的高、寬、縮放比例三個資訊 else: # not using RPN # Now, build the region of interest and label blobs rois_blob = np.zeros((0, 5), dtype=np.float32) labels_blob = np.zeros((0), dtype=np.float32) bbox_targets_blob = np.zeros((0, 4 * num_classes), dtype=np.float32) bbox_inside_blob = np.zeros(bbox_targets_blob.shape, dtype=np.float32) # all_overlaps = [] for im_i in xrange(num_images): labels, overlaps, im_rois, bbox_targets, bbox_inside_weights \ = _sample_rois(roidb[im_i], fg_rois_per_image, rois_per_image, num_classes) # Add to RoIs blob rois = _project_im_rois(im_rois, im_scales[im_i]) batch_ind = im_i * np.ones((rois.shape[0], 1)) rois_blob_this_image = np.hstack((batch_ind, rois)) rois_blob = np.vstack((rois_blob, rois_blob_this_image)) # Add to labels, bbox targets, and bbox loss blobs labels_blob = np.hstack((labels_blob, labels)) bbox_targets_blob = np.vstack((bbox_targets_blob, bbox_targets)) bbox_inside_blob = np.vstack((bbox_inside_blob, bbox_inside_weights)) # all_overlaps = np.hstack((all_overlaps, overlaps)) # For debug visualizations # _vis_minibatch(im_blob, rois_blob, labels_blob, all_overlaps) blobs['rois'] = rois_blob blobs['labels'] = labels_blob if cfg.TRAIN.BBOX_REG: blobs['bbox_targets'] = bbox_targets_blob blobs['bbox_inside_weights'] = bbox_inside_blob blobs['bbox_outside_weights'] = \ np.array(bbox_inside_blob > 0).astype(np.float32) return blobs
下面看看具體是如何讀取圖片資料的:
def _get_image_blob(roidb, scale_inds):這個函式其實就是讀取圖片,然後做尺寸變換,然後儲存成4維矩陣的形式,返回;
def _get_image_blob(roidb, scale_inds): """Builds an input blob from the images in the roidb at the specified scales. """ num_images = len(roidb) processed_ims = [] im_scales = [] for i in xrange(num_images): im = cv2.imread(roidb[i]['image'])#讀取圖片,返回的是一個ndarray的三維的矩陣 if roidb[i]['flipped']:#如果這張圖片是水平對稱的資料,那麼將三維矩陣中的第二維資料(寬)做對稱操作 im = im[:, ::-1, :] target_size = cfg.TRAIN.SCALES[scale_inds[i]]#確定選定的縮放的(最短邊)尺寸的大小 im, im_scale = prep_im_for_blob(im, cfg.PIXEL_MEANS, target_size, cfg.TRAIN.MAX_SIZE)#呼叫函式對圖片進行縮放 im_scales.append(im_scale)#把縮放係數,放到list中 processed_ims.append(im)#把三維矩陣資料作為一個元素放到list中 # Create a blob to hold the input images blob = im_list_to_blob(processed_ims)#呼叫函式,把前面在list中的三維矩陣元素,轉換成4維矩陣的形式 return blob, im_scales
在下面的函式中,作者將list中的3維的元素,轉換成了4維的ndarray,下面看看作者是如何做的:
def im_list_to_blob(ims):#這裡輸入的ims是一個list,其中的每個元素是一個3維的圖片矩陣資料
"""Convert a list of images into a network input.
Assumes images are already prepared (means subtracted, BGR order, ...).
"""
max_shape = np.array([im.shape for im in ims]).max(axis=0)#統計所有圖片的height width的最大值
num_images = len(ims)
blob = np.zeros((num_images, max_shape[0], max_shape[1], 3),
dtype=np.float32)#構造一個全部為0的4維的矩陣,暫時的順序是圖片、高、寬、通道
for i in xrange(num_images):
im = ims[i]
blob[i, 0:im.shape[0], 0:im.shape[1], :] = im #把每個圖片對應的資料copy到blob中
# Move channels (axis 3) to axis 1
# Axis order will become: (batch elem, channel, height, width)
channel_swap = (0, 3, 1, 2)#設定矩陣維度變換的引數,最終的4個維度分別對應圖片、通道、高、寬,這與caffe的blob的格式就保持一致了
blob = blob.transpose(channel_swap)
return blob
作者:香蕉麥樂迪--sloanqin--覃元元