numpy pytorch 接口对应_目标检测:数据增强(Numpy+Pytorch)

本文介绍了在目标检测任务中如何利用Numpy和Pytorch实现数据增强,包括随机裁剪、变换亮度、通道交换、对比度调整、饱和度变化和色度变换等方法,以提升模型的泛化能力。
摘要由CSDN通过智能技术生成

上文我们讲了在图像分类问题的数据增强的几种方法,其中很重要的方式为图像的随机裁剪,我们可以轻松地调用Pytorch框架的API加以实现,但是在图像检测问题中,如何实现数据增强的效果呢?由于我们对图像进行了随机裁剪,那么GT boxes的位置信息也会发生变化,可能会被裁剪为一半或者什么的,所以对于检测问题,直接使用Pytorch的API是不可以的,那么我们就从Numpy的底层来实现一个数据增强的程序!

分类问题的数据增强:TeddyZhang:图像分类:数据增强(Pytorch版)​zhuanlan.zhihu.com

需要工程源码的请点赞!!!哈哈哈~

数据格式

已知我们的图像为3通道R/G/B,而且一幅图像标记的Boxes为[N, 4],其中N为一幅图像的真实框数,那么我们就来看看在检测问题中数据增强怎么做的?4维数据分别是[x1, y1, w, h],假设我们的模型的输入图片定义为1024x1024

随机裁剪 (对标记的Boxes进行处理)从图像中随机裁剪一个正方形,边长范围为[0.3*min, max], min为长与宽的最小值

计算真实框的中心点,裁剪区域一定要包含这些中心点

将原始图的GT Boxes变换成裁剪图的GT boxes

去掉那些过小的GT boxes, 不参与训练

# 3. 随机进行裁剪

def random_crop(self, im, boxes, labels):

imh, imw, _ = im.shape

short_size = min(imh, imw)

while True:

# 选择任意一个crop pitch

mode = random.randint(0, 4)

for _ in range(10):

if mode == 0:

w = short_size

else:

w = random.randrange(int(0.3*short_size), short_size) # 从0.3倍的最小边界开始

h = w

x = random.randint(0, imw - w)

y = random.randint(0, imh - h) # 随机选择正方形区域

roi = torch.Tensor([x, y, x+w, y+h])

center = (boxes[:, :2]+boxes[:, 2:]) / 2 # (N,2)维, 中心点

roi2 = roi.expand(len(center), 4) # 把(1,4)expand到(N,4)维

# 1. 选择包含box的roi

mask = (center > roi2[:, :2]) & (center < roi2[:, 2:]) # crop pitch里面包含那个中心点(N,2)

mask = mask[:, 0] & mask[:, 1] # (N, 1)

# any对每个元素进行或运算,对每个元素进行与运算

if not mask.any(): # 如果全为零,舍弃这个crop patch

im, boxes, labels = self.random_getim()

imh, imw, _ = im.shape

short_size = min(imh, imw)

continue

selected_boxes = boxes.index_select(0, mask.nonzero().squeeze(1)) # mask变为(N,)

img = im[y:y+h, x:x+w] # 裁剪区域

selected_boxes[:,0].add_(-x).clamp_(min=0, max=w) # clamp 夹并在x,y之间

selected_boxes[:,1].add_(-y).clamp_(min=0, max=h)

selected_boxes[:,2].add_(-x).clamp_(min=0, max=w)

selected_boxes[:,3].add_(-y).clamp_(min=0, max=h)

# expand_as(x) 表示扩展成x的尺寸

boxes_uniform = selected_boxes / torch.Tensor([w,h,w,h]).expand_as(selected_boxes)

boxeswh = boxes_uniform[:, 2:] - boxes_uniform[:, :2]

# 2. 选择去掉box太小的

mask = (boxeswh[:,0] > self.small_threshold) & (boxeswh[:,1] > self.small_threshold)

if not mask.any(): # 若全部为零,则舍弃

im, boxes, labels = self.random_getim()

imh, imw, _ = im.shape

short_size = min(imh, imw)

continue

selected_boxes_selected = selected_boxes[mask.nonzero().squeeze(1)] # mask变为(N,)

selected_labels = labels.index_select(0, mask.nonzero().squeeze(1))

return img, selected_boxes_selected, selected_labels

其中:tensor.index_select(dim, mask) 在dim维选择mask对应为正的元素

tensor.clamp_(min, max) 把数据夹在(min, max)之间

random.random() 产生0到1的随机数

random.randrange(0, N) 在0到N之间产生随机整数

np.nonzero() 选择不为零的元素

np.squeeze(1) 压缩维度,去掉维度1

tensor.expand(a, b) 把a扩展 b次,和传播机制类似

tensor.expand_as(B) 也是扩展,扩展后的维度和B一致

随机变换亮度

就是把图像加减某个值

# 4. 随机变换亮度 (概率:0.5)

def random_bright(self, im, delta=32):

if random.random() < 0.5:

delta = random.uniform(-delta, delta)

im += delta

im = im.clip(min=0, max=255)

return im

其中:random.uniform(-a, a) 随机在-a到a之间生成数字

np.clip(min,max) 和tensor.clamp效果一样

随机变换通道

# 5. 随机变换通道

def random_swap(self, im):

perms = ((0, 1, 2), (0, 2, 1),

(1, 0, 2), (1, 2, 0),

(2, 0, 1), (2, 1, 0))

if random.random() < 0.5:

swap = perms[random.randrange(0, len(perms))]

im = im[:, :, swap]

return im

随机变换对比度

图片像素点随机乘以某个值,(0.5,1.5)

# 6. 随机变换对比度

def random_contrast(self, im, lower=0.5, upper=1.5):

if random.random() < 0.5:

alpha = random.uniform(lower, upper)

im *= alpha

im = im.clip(min=0, max=255)

return im

随机变换饱和度

就是中间的色彩通道乘以某个值

# 7. 随机变换饱和度

def random_saturation(self, im, lower=0.5, upper=1.5):

if random.random() < 0.5:

im[:, :, 1] *= random.uniform(lower, upper)

return im

随机色度变换

首先把图像转换到HSV空间,然后再加上某个值

# 8. 随机变换色度(HSV空间下(-180, 180))

def random_hue(self, im, delta=18.0):

if random.random() < 0.5:

im[:, :, 0] += random.uniform(-delta, delta)

im[:, :, 0][im[:, :, 0] > 360.0] -= 360.0

im[:, :, 0][im[:, :, 0] < 0.0] += 360.0

return im

随机饱和度和色度变换

变换HSV空间,然后变回到OpenCV的BGR空间

# 9. 扭曲

def for_distort(self, im):

im = cv2.cvtColor(im, cv2.COLOR_BGR2HSV)

self.random_saturation(im)

self.random_hue(im)

im = cv2.cvtColor(im, cv2.COLOR_HSV2BGR)

return im

实验结果:

原始图片(图片源自:源自云从科技人头检测竞赛)

对一张图片进行裁剪,,然后随机进行色彩和对比度等的变化,这样就达到了数据增强的目的,使得模型训练的泛化能力更强~~,可能这个例子不明显,由于随机变换,所以可能色彩没有进行变换,可以看到裁剪后,对应的框的位置没有改变,这就是random_crop所实现的东西!( 图片源自:云从科技人头检测竞赛)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值