这次带来的是Faster R-CNN中的子程序get_data()的代码解析
import cv2
import numpy as np
代码首先导入的是两个库。其中cv2主要是图像方面的库,numpy是科学计算方面的库。
def get_data(input_path):
found_bg = False
all_imgs = {}
classes_count = {}
class_mapping = {}
visualise = True
代码经过了一些的初始化。重新提一下这些变量最后的作用:
all_imgs是一个list,但是他的每个元素都是字典,也就是存放的是每一张图片里面的信息,
比如某张图像的总共有多少个目标,有多少个类等
从便签文件路径中得到所有的图像,类别的数量还有类别
class_count 是各类总共的数量,是一个字典,key是类名,value是该类的数量,
class_mapping 是每个类对应的标签
with open(input_path, 'r') as f:
print('Parsing annotation files')
for line in f:
line_split = line.strip().split(',')
(filename, x1, y1, x2, y2, class_name) = line_split
由于代码太长,我们剪切出一段来慢慢解析。
本段代码一开始是以读取的方式打开了这个输入的路径( with open(input_path, ‘r’) as f:)
将这个路径中的信息逐个读取出来赋值给line(for line in f:)
line.strip().split(',')
其中line.strip()是用来删除字符串头尾指定的字符。
strip()的用法:
Python strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。
注意:该方法只能删除开头或是结尾的字符,不能删除中间部分的字符。
.split(‘,’)是用括号中的符号对前面的字符进行划分,比如:AB→A,B
(filename, x1, y1, x2, y2, class_name) = line_split
将划分的信息分别输送给前面设定好的变量名。
if class_name not in classes_count:
classes_count[class_name] = 1
else:
classes_count[class_name] += 1
现在这个classes_count计算了所有类别所有的数目了。
对图像中的类进行各类总共的数量的计算,如果这个class_name不在之前预存好集内,我们就给这个数据集类加一个key并且赋值为1。
if class_name not in class_mapping:
if class_name == 'bg' and not found_bg:
print('Found class name with special name bg. Will be treated as a'
' background region (this is usually for hard negative mining).')
found_bg = True
class_mapping[class_name] = len(class_mapping)
这里判断class_name 是否在 class_mapping,这里如果发现背景这个标签就把 found_bg设为True。并把这个类设定了位置。这里设置的是长度(len(class_mapping))我们通过设置长度确定各类的标签。用十进制表示,比如这个class_mapping有10个东西,那么我们设置这个位置的class_mapping里面这个标签的位置为第10个。
好了现在class_mapping记载了所有的类别了
if filename not in all_imgs:
all_imgs[filename] = {}
img = cv2.imread(filename)
(rows, cols) = img.shape[:2]
all_imgs[filename]['filepath'] = filename
all_imgs[filename]['width'] = cols
all_imgs[filename]['height'] = rows
all_imgs[filename]['bboxes'] = []
if np.random.randint(0, 6) > 0:
all_imgs[filename]['imageset'] = 'trainval'
else:
all_imgs[filename]['imageset'] = 'test'
现在是对这个名为all_imgs的字典进行赋值,先是对字典内嵌套一个字典(all_imgs[filename] = {}),然后是读取图片(img = cv2.imread(filename))还有图像的尺寸((rows, cols) = img.shape[:2])。下面这段代码保存了图片的路径和长宽
all_imgs[filename]['filepath'] = filename
all_imgs[filename]['width'] = cols
all_imgs[filename]['height'] = rows
all_imgs[filename]['bboxes'] = []
这代码里对bboxes进行了赋空值。然后是对图像划分训练集还是测试集
if np.random.randint(0, 6) > 0:
all_imgs[filename]['imageset'] = 'trainval'
else:
all_imgs[filename]['imageset'] = 'test'
最后对刚刚赋空值的bboxes赋值
all_imgs[filename]['bboxes'].append(
{'class': class_name, 'x1': int(float(x1)), 'x2': int(float(x2)), 'y1': int(float(y1)),
'y2': int(float(y2))})
最后对这个all_imgs里的数据保存到一个数据all_data里。
all_data = []
for key in all_imgs:
all_data.append(all_imgs[key])
真的最后了,把”背景“这类移动到最后一个去
if found_bg:
if class_mapping['bg'] != len(class_mapping) - 1:
key_to_switch = [key for key in class_mapping.keys() if class_mapping[key] == len(class_mapping) - 1][0]
val_to_switch = class_mapping['bg']
class_mapping['bg'] = len(class_mapping) - 1
class_mapping[key_to_switch] = val_to_switch
返回需要的值:
return all_data, classes_count, class_mapping