代码之家  ›  专栏  ›  技术社区  ›  user1631306

python在重叠的平铺中分割图像

  •  0
  • user1631306  · 技术社区  · 7 年前

    我在做图像分类。我的数据非常不平衡。我正在尝试几种方法来克服数据不平衡的问题。其中之一就是对少数族裔进行过抽样。 我拥有的图像已经是高分辨率的(1392x1038),所以我将它们分割成348x256大小的16块。与过采样一样,只需复制少数类。我在考虑用步幅1或2将图像分割成重叠的瓷砖,这样我就有了不同的图像,这也有助于我进行过采样。下面的代码将图像分割为指定数量的定义大小的重叠平铺

    for i in range(0, count):
            start_row_idx = random.randint(0, img_height-target_height-1)
            start_col_idx = random.randint(0, img_width-target_width-1)
    
            if mode == 'rgb':
                patch = img_array[start_row_idx:(start_row_idx+target_height), start_col_idx:(start_col_idx+target_width), :]
            else:
                patch = img_array[start_row_idx:(start_row_idx+target_height), start_col_idx:(start_col_idx+target_width)]
            patches.append(patch)
            idxs.append((start_row_idx, start_col_idx))
    

    我如何才能使其工作,旋转重叠瓷砖与定义的瓷砖数量和大小。

    编辑问题: 在下图中,黑色方块显示了我能够获得的水平步幅和平铺。我想把红色方块做成那种形状。我认为,使用红色类型的裁剪,我将能够获得更多用于过采样的图像。

    enter image description here

    0 回复  |  直到 6 年前
        1
  •  1
  •   rayryeng    7 年前

    正如我们在上面讨论的,你有可能被重叠的瓷砖,所以这已经被解决了。缺少的是旋转瓷砖。我们需要指定一个随机旋转角度,这样我们就可以先生成一个随机角度。

    之后,这只是一个应用仿射变换的问题,仿射变换纯粹是对平铺的旋转,然后附加到列表中。在OpenCV中旋转图像的问题是,当你旋转图像时,它会被裁剪,所以一旦旋转,你就无法获得图像中包含的整个平铺。

    我用了 following post as inspiration 为了解决这个问题,当你旋转时,图像被完全包含。请注意,为了适应旋转并保持旋转结果中包含的整个图像,图像将在尺寸上展开。

    import cv2
    import numpy as np
    
    def rotate_about_center(src, angle):
        h, w = src.shape[:2]
        rangle = np.deg2rad(angle)  # angle in radians
        # now calculate new image width and height
        nw = (abs(np.sin(rangle)*h) + abs(np.cos(rangle)*w))
        nh = (abs(np.cos(rangle)*h) + abs(np.sin(rangle)*w))
        # ask OpenCV for the rotation matrix
        rot_mat = cv2.getRotationMatrix2D((nw*0.5, nh*0.5), angle, 1)
        # calculate the move from the old centre to the new centre combined
        # with the rotation
        rot_move = np.dot(rot_mat, np.array([(nw-w)*0.5, (nh-h)*0.5,0]))
        # the move only affects the translation, so update the translation
        # part of the transform
        rot_mat[0,2] += rot_move[0]
        rot_mat[1,2] += rot_move[1]
        return cv2.warpAffine(src, rot_mat, (int(math.ceil(nw)), int(math.ceil(nh))), flags=cv2.INTER_LANCZOS4)
    

    你使用这个函数,用一个随机角度调用它,然后在完成后保存补丁。当然,您还需要指定最大旋转角度。

    import random
    max_angle = 20 # +/- 20 degrees maximum rotation
    patches = []
    idxs = []
    for i in range(0, count):
        start_row_idx = random.randint(0, img_height-target_height-1)
        start_col_idx = random.randint(0, img_width-target_width-1)
    
        # Generate an angle between +/- max_angle
        angle = (2*max_angle)*random.random() - max_angle
    
        if mode == 'rgb':
            patch = img_array[start_row_idx:(start_row_idx+target_height), start_col_idx:(start_col_idx+target_width), :]
        else:
            patch = img_array[start_row_idx:(start_row_idx+target_height), start_col_idx:(start_col_idx+target_width)]
    
        # Randomly rotate the image
        patch_r = rotate_about_center(patch, angle)
    
        # Save it now
        patches.append(patch_r)
        idxs.append((start_row_idx, start_col_idx))