1 配置文件
“/maskrnn_benchmark/config” 文件夹下可以看到两个文件default.py和paths_catalog.py。default.py是默认的配置文件,paths_catalog.py保存了数据集和模型的保存地址,可以根据自己的情况进行修改。
配置文件的一级选项有:
- INPUT: 输入图像的尺寸、标准化均值和方差、RGB格式转化
- DATASETS: 训练和测试数据集,可以参考paths_catalog.py,设置为list
- DATALOADER: 线程数量、尺寸可被整除数(0 不调整图像尺寸)、每个batch中图像尺寸比率是否兼容
- MODEL:可选项较多,主要是网络结构的参数
- 主干网络、
- FPN、
- Grop_Norm、
- RPN、
- RoI_Head
- RoI_Box_Head
- RoI_Mask_Head
- RoI_KeyPoint_Head
- resnet
- retinanet
- fbnet
- Solver:最大迭代次数、基础学习率、学习类衰减因子、动量、参数衰减因子、warmup参数、checkpoint、batch_size
- Test:batch_size、每张图片检测数量等
- OutDir:保存路径
- Path_CataLog:paths_catalog.py文件路径
抽象类
ImageList
PyTorch 中,网络输入的第一维通常是 batchsize 维,因此,同一个 batch 的所有样本具有相同的 height 和 width.
但是,为了支持在同一个 batch 内的图片能够是不同尺寸和长宽比(aspect ratios)的,该项目新建了 ImageList 类,其能够内部支持 batch 内不同尺寸的图像. 所有的图片进行了补零(padding with zeros),以确保图像尺寸相同,并可以可以根据第一维进行 batch 化. 该类有两个属性,tensors
和image_sizes
,前者是
B
×
C
×
H
×
W
B\times C\times H\times W
B×C×H×W的torch.tensor
,后者是长度为
B
B
B的torch.Size
(
H
×
W
H\times W
H×W)。补零前的图像原始尺寸保存在 image_sizes
属性中,batch 化后的张量保存在 tensors
中.
该项目提供了一个工具函数 - to_image_list
,其输入支持不同的类型,如,tensors
列表,并返回 ImageList
对象.
BoxList
BoxList
类保存了特定图像的边界框数据.bbox
(Nx4 tensor),以及图像的尺寸.size
(
W
×
H
W\times H
W×H,与 image_sizes. image_sizes
相反),属于边界框的模式.mode
(string
),其他域.extra_fields
(dict
)。
此外,还包含了关于边界框几何变换的方法,如,裁剪.crop()
,缩放resize()
翻转.transpose()
,以及模式转换.convert()
.
BoxList的输入边界框格式,支持两种形式:
- xyxy - 每个 box 记为 x1, x2, y1, y2 坐标的形式.
- xywh - 每个 box 记为 x1, y1, w, h 的形式.
另外,每个 BoxList实例还可以包含每个边界框的任意新增信息,如,labels,可见性visibility,概率值probability scores 等.
from maskrcnn_benchmark.data import make_data_loader
from config import cfg
import numpy as np
import matplotlib.pyplot as plt
import math, cv2
def show_img_batch(imgs, targets, index2class):
img = imgs.tensors.permute(0, 2, 3, 1).contiguous().numpy() + np.array([[[102.9801, 115.9465, 122.7717]]])
# img /= 255.0
img = img.astype(np.uint8)
print(np.max(img), np.min(img))
fig = plt.figure()
batch_size = imgs.tensors.shape[0]
num_cols = int(math.ceil(batch_size / 2))
ax = fig.subplots(2, num_cols)
for i in range(ax.shape[1]):
for j in range(ax.shape[0]):
ax[j, i].axis('off')
images = img[j * num_cols + i][:, :, ::-1].copy()
t = targets[j*num_cols + i]
labels = t.extra_fields['labels']
bbox = t.bbox
for l in range(len(labels)):
pt1, pt2 = (bbox[l, 0], bbox[l, 1]), (bbox[l, 2], bbox[l, 3])
print(pt1, pt2)
cv2.rectangle(images, pt1, pt2, (0, 255, 0), thickness=2)
cv2.putText(images, index2class[labels[l]], (pt2[0]-20, pt2[1]-30), cv2.FONT_HERSHEY_COMPLEX, 1.2, (0, 255, 0), 2)
ax[j, i].imshow(images)
print()
plt.show()
# datasets' and models' path can be find in path_catalog
from config import paths_catalog
cfg.SOLVER.IMS_PER_BATCH = 4
cfg.DATALOADER.SIZE_DIVISIBILITY = 32
data_loader = make_data_loader(cfg, is_train=bool, is_distributed=False)
data_iter = iter(data_loader)
images, targets, idx = next(data_iter)
show_img_batch(images, targets, index2class=data_loader.dataset.CLASSES)
for i, img, size, t in zip(idx, images.tensors, images.image_sizes, targets):
print('index: %d' % i)
print('tensor shape:', img.shape, '\ttensor device: ', img.device, '\ttensor dtype: ', img.dtype)
print('original image size: ', size)
print('bbox: ', t.bbox)
print('bbox img size: ', t.size)
print('bbox mode: ', t.mode)
if t.extra_fields is not None:
print('target extra_fields: ')
for k, v in t.extra_fields.items():
print('\t', k, v)
else:
print('target extra_fields is none')
print()
运行结果: