我正在对图像进行分类。我的数据非常不平衡。我正在尝试几种方法来克服数据不平衡的问题。其中之一是对少数民族阶层的过度采样。 我所拥有的图像已经具有高分辨率(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))
如何使它具有定义的图块数量和大小来旋转重叠的图块。
编辑问题: 在下图中,黑色方块显示了我可以得到的水平步幅和图块。我想获得那种形状的红色正方形。我认为,通过红色类型的裁剪,我将可以获得更多的图像以进行超采样。
答案 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))