三通道或单通道图像裁剪与拼接

裁剪

import os
import cv2 as cv
import numpy as np
from tqdm import tqdm

# 单幅影像裁剪
def clip(img_path, save_img, size, repetition):
    img = cv.imread(img_path, -1)  # 加载原图
    save_img = save_img  # 存储路径

    file_name_all = os.path.basename(img_path)
    file_name = file_name_all.split('.')[0]
    end = "." + file_name_all.split('.')[1]

    shape = img.shape
    channels = shape[2]

    if not os.path.exists(save_img):
        os.makedirs(save_img)
    print(f'原图像(h, w, ch):', img.shape)
    size = size  # 裁剪大小: 500x500
    repetition = repetition  # 重复像素
    h, w = (
        img.shape[0],
        img.shape[1],
    )  # img.shape[0]是高, img.shape[1]是宽, img.shape[2]是通道数
    num_h = (h - repetition) // (size - repetition)  # 裁剪后行数
    num_w = (w - repetition) // (size - repetition)  # 裁剪后列数
    img = np.array(img)  # to array
    print(f'不考虑右、下情况下,每行生成{num_w}幅小图')
    print(f'不考虑右、下情况下,每列生成{num_h}幅小图')

    if end == str('.jpg') or end == str('.JPG'):
        flag = [cv.IMWRITE_JPEG_QUALITY, 100]
    elif end == str('.png'):
        flag = [cv.IMWRITE_PNG_COMPRESSION, 0]
    else:
        raise ValueError(" end must be 'jpg' or 'png' ! ")

    # 1.正常范围裁剪:
    if channels == 3:
        shape = (size, size, channels)
    elif channels == 1:
        shape = (size, size)
    else:
        raise ValueError(" channel must be '1' or '3' ! ")

    img_crop = np.zeros(shape)
    image = []
    i, j, k = 0, 0, 0
    for i in range(0, num_h):
        for j in range(0, num_w):
            img_crop = img[
                i * size - i * repetition : i * size - i * repetition + size,
                j * size - j * repetition : j * size - j * repetition + size,
            ]
            image.append(img_crop)

    for k in range(0, (num_h * num_w)):
        image_k = image[k]
        path_image_k = os.path.join(save_img, file_name + '_' + str(k + 1) + end)
        cv.imwrite(path_image_k, image_k, flag)
    print(f'正常裁剪{num_h * num_w}幅图')

    # 2.最下面一行的裁剪:
    img_crop_down = np.zeros(shape)
    image_down = []
    i, j, k = 0, 0, 0
    for j in range(0, num_w):
        img_crop_down = img[
            h - size : h, j * size - j * repetition : j * size - j * repetition + size
        ]
        image_down.append(img_crop_down)

    for k in range(0, num_w):
        image_k = image_down[k]
        path_image_k = os.path.join(
            save_img, file_name + '_' + str(k + 1 + num_h * num_w) + end
        )
        cv.imwrite(path_image_k, image_k, flag)
    print(f'最下面一行裁剪{num_w}幅图')

    # 2.最右边一列的裁剪:
    img_crop_right = np.zeros(shape)
    image_right = []
    i, j, k = 0, 0, 0
    for i in range(0, num_h):
        img_crop_right = img[
            i * size - i * repetition : i * size - i * repetition + size, w - size : w
        ]
        image_right.append(img_crop_right)

    for k in range(0, num_h):
        image_k = image_right[k]
        path_image_k = os.path.join(
            save_img, file_name + '_' + str(k + 1 + num_h * num_w + num_w) + end
        )
        cv.imwrite(path_image_k, image_k, flag)
    print(f'最右边一列裁剪{num_h}幅图')

    # 3.最右下角的一幅小图:
    image_d_r = []
    i, j, k = 0, 0, 0
    img_crop_d_r = img[h - size : h, w - size : w]
    image_d_r.append(img_crop_right)
    path_image = os.path.join(
        save_img, file_name + '_' + str(k + 1 + num_h * num_w + num_w + num_h) + end
    )
    cv.imwrite(path_image, img_crop_d_r, flag)
    print(f'最右下角裁剪1幅图')

# 批量裁剪某一文件夹下所有的图像,保存在指定某一文件夹下
def batch_clip(img_dir, save_dir, size, repetition):
    file_names = [
        filename
        for filename in os.listdir(img_dir)
        if filename.endswith("jpg")
        or filename.endswith("JPG")
        or filename.endswith("png")
    ]
    
    print('图像加载完毕!开始裁剪!')

    for file_name in tqdm(file_names):
        img_path = os.path.join(img_dir, file_name)
        clip(
            img_path,  # 选择要裁剪的图像
            save_dir,  # 裁剪后小图的存储路径
            size=size,  # 裁剪正方形的大小
            repetition=repetition,  # 像素重合距离
        )


if __name__ == "__main__":
    img_dir = 'test'
    save_dir = 'test_results'
    size = 512
    repetition = 128

    batch_clip(img_dir, save_dir, size=size, repetition=repetition)

拼接

import os
import numpy as np
import cv2 as cv


def main(ori_img, croped_path, output_path, output_name, size, repetition):
    ori_img = cv.imread(ori_img, -1)
    croped_path = croped_path
    output_path = output_path
    output_name = output_name
    size = size
    repetition = repetition
    h, w = ori_img.shape[0], ori_img.shape[1]  # 获取原始图像的高和宽
    num_h = (h - repetition) // (size - repetition)  # 裁剪后行数
    num_w = (w - repetition) // (size - repetition)  # 裁剪后列数
    img = np.zeros((h, w))  # 创建与原始图像等大的画布
    from natsort import natsorted
    all_img = natsorted(os.listdir(croped_path))  # ['1.jpg', '10.jpg', '100.jpg', ...]
    all_img.sort(key=lambda x: int(x[:-4]))  # ['1.jpg', '2.jpg', '3.jpg', ...]

    # 1.正常范围拼接
    i, j = 0, 0
    for i in range(0, num_h):
        for j in range(0, num_w):
            small_img_path = os.path.join(croped_path, all_img[i * num_w + j])
            print(f'正常范围拼接:{all_img[i * num_w + j]}')
            small_img = cv.imread(small_img_path, -1)
            small_img = np.array(small_img)
            img[
            i * (size - repetition):i * (size - repetition) + size,
            j * (size - repetition):j * (size - repetition) + size
            ] = small_img[0:size, 0:size]

    # 2.最下面一行的拼接:
    i, j = 0, 0
    for j in range(0, num_w):
        small_img_path = os.path.join(croped_path, all_img[num_h * num_w + j])
        print(f'最下面一行的拼接:{all_img[num_h * num_w + j]}')
        small_img = cv.imread(small_img_path, -1)
        small_img = np.array(small_img)
        img[
        h - size:h,
        j * (size - repetition):j * (size - repetition) + size
        ] = small_img[0:size, 0:size]

    # 3.最右边一列的拼接
    i, j = 0, 0
    for i in range(0, num_h):
        small_img_path = os.path.join(croped_path, all_img[num_h * num_w + num_w + i])
        print(f'最右边一列的拼接:{all_img[num_h * num_w + num_w + i]}')
        small_img = cv.imread(small_img_path, -1)
        small_img = np.array(small_img)
        img[
        i * (size - repetition):i * (size - repetition) + size,
        w - size:w
        ] = small_img[0:size, 0:size]

    # 4.最右下角的一幅小图
    small_img_path = os.path.join(croped_path, all_img[-1])
    print(f'最右下角的一幅小图拼接:{all_img[-1]}')
    small_img = cv.imread(small_img_path, -1)
    small_img = np.array(small_img)
    img[
    h - size:h,
    w - size:w
    ] = small_img[0:size, 0:size]

    if not os.path.exists(output_path):
        os.makedirs(output_path)
    cv.imwrite(os.path.join(output_path, output_name), img, [cv.IMWRITE_PNG_COMPRESSION, 0])


if __name__ == '__main__':
    main(ori_img='80.JPG',  # 读取原图,用于创建画布
         croped_path='pic',  # 读取存放小图的路径
         output_path='results',  # 设置结果输出路径
         output_name='80.png',  # 设置拼接后的图像名
         size=256,  # 小图大小
         repetition=50  # 像素重合距离
         )

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卖报的大地主

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值