将图像等分裁剪为想要的尺寸

在训练神经网络时,自己的数据可能分辨率过高,导致训练效果差,甚至还会爆显存,所以需要把图片进行裁剪

思路也非常简单,就是通过两层循环把每一裁剪子图的RGB提取出来,写入新文件

但是如果原图的尺寸不能整除子图的尺寸怎么办呢?

这里考虑进行填充

首先需要明确原始分辨率,和要裁剪成多大的图片,比如我的图片是2736*3648,目标分辨率为608。

其实这个尺寸还可以,因为2736 ÷ 608 = 4.5,3648 ÷ 608 = 6,也就是会有6张图片不足608*608,所以要进行填充操作。

填充思路也很简单,循环结束的条件就是当前x+裁剪后图像分辨率608>2736,此时会有一段图像未进行裁剪,那么就取从当前x一直到图片末尾的像素,并在其x方向填充(目标尺寸 - (图像原x - 当前x))

但如果有小伙伴x无法整除(目标尺寸),y也无法整除,只需要在最外层循环结束后,再判断一次y方向是否有剩余就好了,方法和判断x的一样。如果x方向最后有剩余,y方向也有剩余,那么到最后一张图片需要进行两个方向的填充。

2021年12月20日重写

空下来了看之前自己写的代码,觉得思路有很大的问题,于是用新思路重写了一遍。。

主要是大图无法等分成目标分辨率的小图,会涉及到填充操作。在之前的方法中我采用对裁剪后的小图进行填充,这样的操作是重复的。于是我在裁剪之前对图像进行判断,其宽与高是否为目标分辨率的整倍数,若不为整倍数则直接对大图进行填充,然后再对填充后的大图进行裁剪,便省去了每次裁剪时都要对填充的判断。

max_y, max_x = img.shape[0], img.shape[1]
# 若不能等分,则填充至等分
if max_x % target_size != 0:
    padding_x = target_size - (max_x % target_size)
    img = cv2.copyMakeBorder(img, 0, 0, 0, padding_x, cv2.BORDER_CONSTANT, value=padding)
    max_x = img.shape[1]
if max_y % target_size != 0:
    padding_y = target_size - (max_y % target_size)
    img = cv2.copyMakeBorder(img, 0, padding_y, 0, 0, cv2.BORDER_CONSTANT, value=padding)
    max_y = img.shape[0]

然后判断填充后的大图的宽与高分别能被目标分辨率分割成多少图

h_count = int(max_x / target_size)
v_count = int(max_y / target_size)

之后便用最传统的双层循环进行裁剪和保存 

    count = 0
    for v in range(v_count):
        for h in range(h_count):
            x_begin = h * target_size
            x_end = (h + 1) * target_size
            y_begin = v * target_size
            y_end = (v + 1) * target_size
            cropImg = img[y_begin:y_end, x_begin:x_end]  # 裁剪图像
            target_path = pic_out_path + file_name + '_' + str(count) + '.jpg'
            cv2.imwrite(target_path, cropImg)  # 写入图像路径
            count += 1

完整代码如下:

# ---------------------------------------------------#
#   裁剪:
#       img:图片(cv格式)
#       target_size: 目标尺寸(仅支持正方形)
#       file_name: 不含扩展名的文件名
#       pic_out_path: 输出文件夹
#       padding: 填充颜色(B,G,R)
# ---------------------------------------------------#
def clip(img, target_size, file_name, pic_out_path, padding=(0, 0, 0)):
    max_y, max_x = img.shape[0], img.shape[1]
    # 若不能等分,则填充至等分
    if max_x % target_size != 0:
        padding_x = target_size - (max_x % target_size)
        img = cv2.copyMakeBorder(img, 0, 0, 0, padding_x, cv2.BORDER_CONSTANT, value=padding)
        max_x = img.shape[1]
    if max_y % target_size != 0:
        padding_y = target_size - (max_y % target_size)
        img = cv2.copyMakeBorder(img, 0, padding_y, 0, 0, cv2.BORDER_CONSTANT, value=padding)
        max_y = img.shape[0]

    h_count = int(max_x / target_size)
    v_count = int(max_y / target_size)

    count = 0
    for v in range(v_count):
        for h in range(h_count):
            x_start = h * target_size
            x_end = (h + 1) * target_size
            y_start = v * target_size
            y_end = (v + 1) * target_size
            cropImg = img[y_start:y_end, x_start:x_end]  # 裁剪图像
            target_path = pic_out_path + file_name + '_' + str(count) + '.jpg'
            cv2.imwrite(target_path, cropImg)  # 写入图像路径
            count += 1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值