python在重叠和旋转的瓷砖中分割图像

时间:2019-06-02 05:29:24

标签: python opencv image-processing

我正在对图像进行分类。我的数据非常不平衡。我正在尝试几种方法来克服数据不平衡的问题。其中之一是对少数民族阶层的过度采样。 我所拥有的图像已经具有高分辨率(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

1 个答案:

答案 0 :(得分:1)

如上所述,您的图块可能会重叠,因此已经得到解决。缺少的是旋转瓷砖。我们需要指定一个随机的旋转角度,以便首先生成一个随机的角度。

此后,仅需应用仿射变换(纯粹是对图块进行旋转),然后附加到列表即可。在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))