yolov1代码解析(2):pascal_voc.py文件分析

yolov1代码解析(2):pascal_voc.py文件分析

这里我们主要讨论batch中的label是由什么组成,并由什么产生的。

//生成gt_labels(txt.中涉到的所有的图片的jpg文件和label信息)
def load_labels(self):		
	if self.phase == 'train':
           	txtname = os.path.join(
               		self.data_path, 'ImageSets', 'Main', 'trainval.txt')
        else:
        	txtname = os.path.join(
                	self.data_path, 'ImageSets', 'Main', 'test.txt')
        with open(txtname, 'r') as f:
        	self.image_index = [x.strip() for x in f.readlines()]
        gt_labels = []
        for index in self.image_index:		
		label, num = self.load_pascal_annotation(index)
            	if num == 0:
                	continue
            	imname = os.path.join(self.data_path, 'JPEGImages', index + '.jpg')
            	gt_labels.append({'imname': imname, 'label': label, 'flipped': False})
        print('Saving gt_labels to: ' + cache_file)
        with open(cache_file, 'wb') as f:
        	pickle.dump(gt_labels, f)
        return gt_labels

对这段代码进行分析:
这里不考虑存在缓存文件的情况,从函数名称我们可以看到该函数负责加载label,首先获取训练集或测试集中存储的图片名称序列(并非.jpg文件,可以理解为xml文件去除后缀的部分),存储在self.image_index中,之后调用load_pascal_annotation这个函数,该函数返回label和num(xml文件中包含object的数量)这两个数据。接着使用imname存储对应.jpg文件的路径。最终该函数的返回值gt_labels由三部分(分别对应jpg图片索引,label,是否翻转)

//生成每张图片对应的label和num
def load_pascal_annotation(self, index):
	imname = os.path.join(self.data_path, 'JPEGImages', index + '.jpg')
	im = cv2.imread(imname)
	h_ratio = 1.0 * self.image_size / im.shape[0]
	w_ratio = 1.0 * self.image_size / im.shape[1]
	label = np.zeros((self.cell_size, self.cell_size, 25))
        filename = os.path.join(self.data_path, 'Annotations', index + '.xml')
        tree = ET.parse(filename)
        objs = tree.findall('object')
        for obj in objs:
        	bbox = obj.find('bndbox')
                x1 = max(min((float(bbox.find('xmin').text) - 1) * w_ratio, self.image_size - 1), 0)
                y1 = max(min((float(bbox.find('ymin').text) - 1) * h_ratio, self.image_size - 1), 0)
                x2 = max(min((float(bbox.find('xmax').text) - 1) * w_ratio, self.image_size - 1), 0)
                y2 = max(min((float(bbox.find('ymax').text) - 1) * h_ratio, self.image_size - 1), 0)
                cls_ind = self.class_to_ind[obj.find('name').text.lower().strip()]
                boxes = [(x2 + x1) / 2.0, (y2 + y1) / 2.0, x2 - x1, y2 - y1]
                x_ind = int(boxes[0] * self.cell_size / self.image_size)
                y_ind = int(boxes[1] * self.cell_size / self.image_size)
                if label[y_ind, x_ind, 0] == 1:
                	continue
                label[y_ind, x_ind, 0] = 1
                label[y_ind, x_ind, 1:5] = boxes
                label[y_ind, x_ind, 5 + cls_ind] = 1
        return label, len(objs)  

对这段代码进行分析:
考虑到xml里的x和y信息来源为没有调整尺寸的图像,但是模型中输入的图像为448 * 448,因此需要将x和y的相关信息按输入图像比例进行调整h_ratio和w_ratio对应了调整的比例。之后开始对xml文件进行解析,寻找xml文件的object字段,将每个object内的x,y信息按照之前的比例信息进行调整。boxes存储的信息等价为[x_center, y_center, width, height]。x_ind和y_ind分别对应中心点所在的cell的行列值。cls_ind存储的为cell负责的object对应的类别数字。label[y_ind, x_ind, 0]作为标志位,表示该cell是否对object负责。label[y_ind, x_ind, 1:5]存储的是坐标的绝对信息。 label[y_ind, x_ind, 5 + cls_ind]是在最后的20列中选择cls_ind对应的类别数字进行标记。

你可能感兴趣的:(yolov1代码解析(2):pascal_voc.py文件分析)