mmcv基本用法

目标检测的Swin Transformer是基于mmdetection的,而mmdetection是一个基于 PyTorch 的目标检测开源工具箱,它是 OpenMMLab 项目的一部分。

OpenMMLab 的其他项目

  • MMCV: OpenMMLab 计算机视觉基础库
  • MMClassification: OpenMMLab 图像分类工具箱
  • MMDetection: OpenMMLab 目标检测工具箱
  • MMDetection3D: OpenMMLab 新一代通用 3D 目标检测平台
  • MMSegmentation: OpenMMLab 语义分割工具箱
  • MMAction2: OpenMMLab 新一代视频理解工具箱
  • MMTracking: OpenMMLab 一体化视频目标感知平台
  • MMPose: OpenMMLab 姿态估计工具箱
  • MMEditing: OpenMMLab 图像视频编辑工具箱
  • MMOCR: OpenMMLab 全流程文字检测识别理解工具包
  • MMGeneration: OpenMMLab 图片视频生成模型工具箱

MMCV是基础库,涉及了诸多基础操作。在mmdection和Swin TransformerOD 中都会用到,因此记录一下MMCV的基本用法。本文只列出了部分功能,全部功能的说明可以从下面的网址查到

Video - mmcv 1.3.3 documentation

图像处理

MMCV对图像的操作包括:图像的读取、写入、显示、色彩空间转换、更改尺寸、旋转、翻转、剪切、填充。MMCV和opencv的指令非常相似,部分指令如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
import mmcv
img = mmcv.imread('test.jpg')#读取图片
img = mmcv.imread('test.jpg', flag='grayscale') #以灰度图读取
mmcv.imwrite(img, 'out.jpg')#写入图片
img = mmcv.imfrombytes(data)#从字节读取图像
mmcv.imresize(img, (1000, 600), return_scale=True)#更改尺寸到1000*600
mmcv.imresize_like(img, dst_img, return_scale=False)#更改尺寸到和另一个图片一样
mmcv.imrescale(img, 0.5)#按比例调整
# 裁剪图片
bboxes = np.array([10, 10, 100, 120])#尺寸是四个点的坐标x1,y1,x2,y2
patch = mmcv.imcrop(img, bboxes)
#填充图片
img_ = mmcv.impad(img, shape=(1000, 1200), pad_val=0)#填充图片到1000*1200的尺寸,补齐像素值是0
img_ = mmcv.impad(img, padding=(10, 20, 30, 40), pad_val=(100, 50, 200))#在图片外围填充,padding元组内是(左右上下)填充值是三个通道的值
img_ = mmcv.impad_to_multiple(img, 32)#填充后使每个边缘都是32的倍数
#显示图片
mmcv.imshow(img)
#显示区域边框
bboxes = np.array([[0, 0, 50, 50], [20, 20, 60, 60]])
mmcv.imshow_bboxes(img, bboxes)

视频处理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#读取视频
video = mmcv.VideoReader('test.mp4')
print(len(video),video.width, video.height, video.resolution, video.fps)#视频帧数、宽、高、分辨率、fps
#可以用迭代器来读取视频的每一帧
for frame in video:
    print(frame.shape)
#也可以读取指定的帧
img = video.read()#读取下一帧
img = video[100]#读取某一帧
img = video[5:10]#读取一些帧
#将视频分成帧并保存到文件夹
video.cvt2frames('out_dir')
#由帧生成视频
mmcv.frames2video('out_dir', 'test.avi')

#剪辑视频 (是ffmpeg指令的封装)
mmcv.cut_video('test.mp4', 'clip1.mp4', start=3, end=10, vcodec='h264')#截取一段视频
mmcv.concat_video(['clip1.mp4', 'clip2.mp4'], 'joined.mp4', log_level='quiet')#拼接视频
mmcv.resize_video('test.mp4', 'resized1.mp4', (360, 240))#缩放视频到360*240
mmcv.resize_video('test.mp4', 'resized2.mp4', ratio=2)#缩放视频2倍

文件IO

MMCV原生支持json、yaml和pickle三种格式的文件加载。也可以自己拓展加载格式。

1
2
3
4
5
6
7
#直接从文件加载数据
data = mmcv.load('test.json')
data = mmcv.load('test.yaml')
data = mmcv.load('test.pkl')
#将数据转存为字符串
json_str = mmcv.dump(data, file_format='json')
mmcv.dump(data, 'out.pkl')#将转存数据输出

可以将文件中的数据读成列表或字典,假设a.txt中的数据是

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
a
b
c
d
e
>>> mmcv.list_from_file('a.txt')
['a', 'b', 'c', 'd', 'e']
>>> mmcv.list_from_file('a.txt', offset=2)
['c', 'd', 'e']
>>> mmcv.list_from_file('a.txt', max_num=2)
['a', 'b']
>>> mmcv.list_from_file('a.txt', prefix='/mnt/')
['/mnt/a', '/mnt/b', '/mnt/c', '/mnt/d', '/mnt/e']

假设a.txt中的数据是

1
2
3
4
5
6
7
1 cat
2 dog cow
3 panda
>>> mmcv.dict_from_file('b.txt')
{'1': 'cat', '2': ['dog', 'cow'], '3': 'panda'}
>>> mmcv.dict_from_file('b.txt', key_type=int)
{1: 'cat', 2: ['dog', 'cow'], 3: 'panda'}

CNN层构建

在进行实验时,可能需要尝试使用同一类型的不同层,但又不想总是修改代码。MMCV提供了层构建方法,该方法可以根据字典来构建层,从而可以用configs加载,也可以通过命令行参数指定这些层。

例如:

1
2
cfg = dict(type='Conv3d')
layer = build_conv_layer(cfg, in_channels=3, out_channels=8, kernel_size=3)
  • build_conv_layer: 支持类型有:Conv1d, Conv2d, Conv3d, Conv (alias for Conv2d).
  • build_norm_layer:支持类型有: BN1d, BN2d, BN3d, BN (alias for BN2d), SyncBN, GN, LN, IN1d, IN2d, IN3d, IN (alias for IN2d).
  • build_activation_layer: 支持类型有: ReLU, LeakyReLU, PReLU, RReLU, ReLU6, ELU, Sigmoid, Tanh, GELU.
  • build_upsample_layer: 支持类型有: nearest, bilinear, deconv, pixel_shuffle.
  • build_padding_layer: 支持类型有: zero, reflect, replicate.

MMCV还支持使用自定义层和操作来拓展层构建方法。

首先编写并注册自己的模块。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from mmcv.cnn import UPSAMPLE_LAYERS

@UPSAMPLE_LAYERS.register_module()
class MyUpsample:

    def __init__(self, scale_factor):
        pass

    def forward(self, x):
        pass

然后将自己的模块MyUpsample导入到某个地方(例如__init__.py中)再使用。

1
2
cfg = dict(type='MyUpsample', scale_factor=2)
layer = build_upsample_layer(cfg)

MMCV还提供常见的模块捆绑包,以方便网络搭建。 ConvModule是卷积层、标准化层、和激活层的捆绑包

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# conv + bn + relu
conv = ConvModule(3, 8, 2, norm_cfg=dict(type='BN'))
# conv + gn + relu
conv = ConvModule(3, 8, 2, norm_cfg=dict(type='GN', num_groups=2))
# conv + relu
conv = ConvModule(3, 8, 2)
# conv
conv = ConvModule(3, 8, 2, act_cfg=None)
# conv + leaky relu
conv = ConvModule(3, 8, 3, padding=1, act_cfg=dict(type='LeakyReLU'))
# bn + conv + relu
conv = ConvModule(3, 8, 2, norm_cfg=dict(type='BN'), order=('norm', 'conv', 'act'))

MMCV还封装了一些权重初始化方法,例如

1
2
3
conv1 = nn.Conv2d(3, 3, 1)
normal_init(conv1, std=0.01, bias=0)
xavier_init(conv1, distribution='uniform')

类似的还包括

  • constant_init
  • xavier_init
  • normal_init
  • uniform_init
  • kaiming_init
  • caffe2_xavier_init
  • bias_init_with_prob

除了Torchvision预训练模型外,MMCV还提供以下CNN的预训练模型,

  • VGG Caffe
  • ResNet Caffe
  • ResNeXt
  • ResNet with Group Normalization
  • ResNet with Group Normalization and Weight Standardization
  • HRNetV2
  • Res2Net
  • RegNet

MMCV中的模型路径放在JSON文件中,open-mmlab.json默认在~/.cache/mmcv下,或者如果有MMCV_HOME环境变量的话,在MMCV_HOME下。MMCV_HOME的优先级更高。

See Also