深度学习图片预处理:augmentation

内容

1.前言

2.带注释代码

3.具体分析


前言

在深度学习中,图像的数据增强是很重要的部分,本篇文章以CPN (Cascaded Pyramid Network for Multi-Person Pose Estimation)中的数据增强代码为例,进行分析。


带注释代码

def data_augmentation(self, img, label, operation):

        #随机裁剪
        height, width = img.shape[0], img.shape[1]
        center = (width / 2., height / 2.)
        n = label.shape[0]  #label:[num_class,3],num_class=17,3=[x,y,valid]
        affrat = random.uniform(self.scale_factor[0], self.scale_factor[1]) #关于裁剪的参数
        
        halfl_w = min(width - center[0], (width - center[0]) / 1.25 * affrat) #affrat大于1.25的时候不进行裁剪
        halfl_h = min(height - center[1], (height - center[1]) / 1.25 * affrat)
        img = skimage.transform.resize(img[int(center[1] - halfl_h): int(center[1] + halfl_h + 1),
                             int(center[0] - halfl_w): int(center[0] + halfl_w + 1)], (height, width))
          #因为[a:b]实际上是取到a~b-1,所以后面要+1
        for i in range(n):
            label[i][0] = (label[i][0] - center[0]) / halfl_w * (width - center[0]) + center[0]  #x
            label[i][1] = (label[i][1] - center[1]) / halfl_h * (height - center[1]) + center[1]  #y
            label[i][2] *= (
            (label[i][0] >= 0) & (label[i][0] < width) & (label[i][1] >= 0) & (label[i][1] < height))  #valid

        # 随机水平翻转
        if operation == 1:
            img = cv2.flip(img, 1)
            #cv2.flip(img,args)  
            # args =1	水平翻转
            # args =0	垂直翻转
            # args =-1	水平垂直翻转
            cod = []
            allc = []
            for i in range(n):
                x, y = label[i][0], label[i][1]
                if x >= 0:
                    x = width - 1 - x  #对关键点label里的x进行水平翻转
                cod.append((x, y, label[i][2]))  
            for (q, w) in self.symmetry: # symmetry = [(1, 2), (3, 4), (5, 6), (7, 8), (9, 10), (11, 12), (13, 14), (15, 16)]
                cod[q], cod[w] = cod[w], cod[q]  #水平翻转之后左右也会发生改变,例如人的左手镜像后会变成右手
            for i in range(n):
                allc.append(cod[i][0])
                allc.append(cod[i][1])
                allc.append(cod[i][2])
            label = np.array(allc).reshape(n, 3)  #经过水平翻转,以及左右标注调整之后的label

        # 随机旋转
        if operation > 1:      
            angle = random.uniform(0, self.rot_factor)   # rot_factor=45,随机45度内的旋转
            if random.randint(0, 1):  # 得到(0,1)之间的一个随机int数,所以只有0或者1,这里保证可以+45度或者-45度进行旋转
                angle *= -1
            rotMat = cv2.getRotationMatrix2D(center, angle, 1.0) # rotMat仿射变换矩阵,参数1表示进行等比例的缩放
            img = cv2.warpAffine(img, rotMat, (width, height))  # warpAffine进行仿射变换。
            
            allc = []
            for i in range(n):
                x, y = label[i][0], label[i][1]
                v = label[i][2]
                coor = np.array([x, y])
                if x >= 0 and y >= 0:
                    R = rotMat[:, : 2]
                    W = np.array([rotMat[0][2], rotMat[1][2]])
                    coor = np.dot(R, coor) + W
                allc.append(int(coor[0]))
                allc.append(int(coor[1]))
                v *= ((coor[0] >= 0) & (coor[0] < width) & (coor[1] >= 0) & (coor[1] < height))
                # 假如x或者y不在图内了,则v变为0,即不可见
                allc.append(int(v))
            label = np.array(allc).reshape(n, 3).astype(np.int)# 经过随机旋转,调整之后的label
        return img, label

具体分析

1.随机裁剪

        for i in range(n):
            label[i][0] = (label[i][0] - center[0]) / halfl_w * (width - center[0]) + center[0]  #x
            label[i][1] = (label[i][1] - center[1]) / halfl_h * (height - center[1]) + center[1]  #y
            label[i][2] *= (
            (label[i][0] >= 0) & (label[i][0] < width) & (label[i][1] >= 0) & (label[i][1] < height))  #valid

对于label中的坐标x来说,不失一般性,设x<center[0]。

a阶段:裁剪之后,center[0]变为halfl_w,

b阶段:图像resize到(height, width),所以又resize回center[0]。

裁剪时保持不变的部分为center[0]-x部分。所以这一部分在a和b阶段对于整幅图的比例是保持不变的。所以从a阶段变为b阶段后,这一部分大小放缩为(center[0]-x)/halfl_w*center[0],所以x此时大小为center[0]-(center[0]-x)/halfl_w*center[0]=center[0]+(x-center[0])/halfl_w*center[0]。因为width - center[0]= center[0],所以分析结果同上面代码一致。

2.随机旋转

            for i in range(n):
                x, y = label[i][0], label[i][1]
                v = label[i][2]
                coor = np.array([x, y])
                if x >= 0 and y >= 0:
                    R = rotMat[:, : 2]
                    W = np.array([rotMat[0][2], rotMat[1][2]])
                    coor = np.dot(R, coor) + W

opencv中得到的仿射矩阵rotMat如下(下图转载自此):

M=\begin{pmatrix} \alpha & -\beta &(1-\alpha)center_x-\beta center_y \ -\beta& \alpha &\beta center_x-(1-\alpha) center_y \ \end{pmatrix}

由此可以直观的认识R和W的具体作用,所以coor = np.dot(R, coor) + W即为将关键点的坐标进行一个仿射变换。


以上代码的注释都是个人的理解,转载请注明出处,要是有错误或考虑不周的地方欢迎指出。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值