基于Python的图片批量切割与合并(保持原像素不变,不会出现像素大小不匹配、填充黑边的问题)

  • 前言
  • 效果图
  • 1、批量读取文件
  • 2、清空目标目录方法(配合切割图片方法使用)
  • 3、批量切割图片(像素不足自动补全)
  • 4、切割图片合成大图片(此处并不是最终处理完成)
  • 5、最终处理(根据原图的尺寸,将多余的像素去除)
  • 6、完整代码

前言

1、本文介绍了基于Python实现的图片切割后按原尺寸合并还原的方法。
2、本文前面详细介绍了各个方法,文末提供了完整代码。
3、本文需要自行填充一些路径,具体请看文末完整代码中的中文信息。
4、本文适配的MacOS解决了目录会自动生成.DS_Store文件的问题。
5、本文的逻辑将会是从切割到复原的全部流程,代码并不会在切割之后停下。
5、本文的逻辑中,存放切割后小图片的目录是作为临时目录,在对下一张图片处理之前将会把此文件夹清空,若需要对小图片做一些操作,可以在文末完整代码对应位置上添加流程。

在一般的图像切割与合并博文中,基本都不会考虑固定尺寸切割最后会导致尺寸损失或尺寸变大,体现就是图片的像素变少了,或者加上了没必要的多余像素。
本文在基于网络上的一些切割合并图像文章之后,实现了对一个目录内所有的图像进行切割、合并的操作,并且能保持像素数量与原图尺寸,不会出现图像尺寸的变化。

效果图

1、批量读取文件

调用os,读取目录下的所有文件,同时排除了MacOS系统自动生成的.DS_Store文件。

# 加载图片列表
def round_read_file(file_path):image_name_list = []for file_name in os.listdir(file_path):# 排除MacOS的.DS_Store文件,Windows下不受影响。if file_name != '.DS_Store':print("加载图片:"+str(file_path)+str(file_name))image_name_list.append(str(file_name))print("总计加载图片数量" + str(len(image_name_list)))return image_name_list

2、清空目标目录方法(配合切割图片方法使用)

# 清空TEMP
# dir_path:需要清空的目录路径
def del_files(dir_path):# os.walk会得到dir_path下各个后代文件夹和其中的文件的三元组列表,顺序自内而外排列,for root, dirs, files in os.walk(dir_path, topdown=False):# 第一步:删除文件for name in files:os.remove(os.path.join(root, name))  # 删除文件# 第二步:删除空文件夹for name in dirs:os.rmdir(os.path.join(root, name)) # 删除一个空目录print("clear done!!")

3、批量切割图片(像素不足自动补全)

# 切割
# orgPath:加载图片所在路径
def qg(orgPath):del_files("切割后的小图片要保存在的目录/")global static_colsglobal static_rows# 目标分割大小DES_HEIGHT = 1500DES_WIDTH = 1500# 获取图像信息path_img = orgPath# 获取原始高分辨的图像的属性信息src = cv2.imread(path_img)height = src.shape[0]width = src.shape[1]# 把原始图像边缘填充至分割大小的整数倍padding_height = math.ceil(height / DES_HEIGHT) * DES_HEIGHTpadding_width = math.ceil(width / DES_WIDTH) * DES_WIDTH# 将padding图像与原始图像进行融合,使得原始padding_img = np.random.randint(0, 255, size=(padding_height, padding_width, 3)).astype(np.uint8)padding_img[0:height + 0, 0:width + 0] = srcimg = padding_img  # 读取彩色图像,图像的透明度(alpha通道)被忽略,默认参数;灰度图像;读取原始图像,包括alpha通道;可以用1,0,-1来表示sum_rows = img.shape[0]  # 高度sum_cols = img.shape[1]  # 宽度cols = DES_WIDTHrows = DES_HEIGHTsave_path = "切割后的小图片要保存在的目录/".format(cols, rows)  # 切割后的照片的存储路径static_rows = int(sum_rows / rows)static_cols = int(sum_cols / cols)filename = os.path.split(path_img)[1]for i in range(int(sum_cols / cols)):for j in range(int(sum_rows / rows)):cv2.imwrite(save_path + os.path.splitext(filename)[0] + '_' + str(j) + '_' + str(i) + os.path.splitext(filename)[1],img[j * rows:(j + 1) * rows, i * cols:(i + 1) * cols, :])

4、切割图片合成大图片(此处并不是最终处理完成)

# 合并分割图像,指定行列数
# merge_path:切割后的小图片所在路径
# num_of_cols:多少列
# num_of_rows:多少行
# target_path:合成后的目标图片保存路径
# file_name:合成后的文件名称
def merge_picture(merge_path, num_of_cols, num_of_rows, target_path, file_name):filename = os.listdir(merge_path)# 排除MacOS的.DS_Store文件if filename[0] == '.DS_Store':filename.remove('.DS_Store')full_path = os.path.join(merge_path, filename[0])shape = cv2.imread(full_path).shape  # 三通道的影像需把-1改成1cols = shape[1]rows = shape[0]channels = shape[2]dst = np.zeros((rows * num_of_rows, cols * num_of_cols, channels), np.uint8)for i in range(len(filename)):full_path = os.path.join(merge_path, filename[i])img = cv2.imread(full_path, -1)cols_th = int(full_path.split("_")[-1].split('.')[0])rows_th = int(full_path.split("_")[-2])roi = img[0:rows, 0:cols, :]dst[rows_th * rows:(rows_th + 1) * rows, cols_th * cols:(cols_th + 1) * cols, :] = roicv2.imwrite(target_path + "merge-" + file_name, dst)

5、最终处理(根据原图的尺寸,将多余的像素去除)

# 最终尺寸切割
# real_org_file_path:真正的原图所在的文件夹
# real_org_file_name:真正的原图的名称
# org_path:合成后的带有多余像素的图片所在路径
# fin_path:最终成品图保存的位置
# org_file_name:合成后带有多余像素的图片名字
# fin_file_name:最终成品图的名字
def cp(real_org_file_path, real_org_file_name, org_path, fin_path, org_file_name, fin_file_name):from PIL import Imageimg = Image.open(org_path+org_file_name)  # 打开chess.png文件,并赋值给imgorg_img = Image.open(real_org_file_path+real_org_file_name)region = img.crop((0, 0, org_img.width, org_img.height))  # 0,0表示要裁剪的位置的左上角坐标,w长 h宽。region.save(fin_path+fin_file_name)  # 将裁剪下来的图片保存

6、完整代码

import math
import os
import cv2
import numpy as np
from PIL import Image
Image.MAX_IMAGE_PIXELS = 2300000000
static_cols = -1
static_rows = -1
# 清空TEMP
# dir_path:需要清空的目录路径
def del_files(dir_path):# os.walk会得到dir_path下各个后代文件夹和其中的文件的三元组列表,顺序自内而外排列,for root, dirs, files in os.walk(dir_path, topdown=False):# 第一步:删除文件for name in files:os.remove(os.path.join(root, name))  # 删除文件# 第二步:删除空文件夹for name in dirs:os.rmdir(os.path.join(root, name)) # 删除一个空目录print("clear done!!")
# 切割
# orgPath:加载图片所在路径
def qg(orgPath):del_files("切割后的小图片要保存在的目录/")global static_colsglobal static_rows# 目标分割大小DES_HEIGHT = 1500DES_WIDTH = 1500# 获取图像信息path_img = orgPath# 获取原始高分辨的图像的属性信息src = cv2.imread(path_img)height = src.shape[0]width = src.shape[1]# 把原始图像边缘填充至分割大小的整数倍padding_height = math.ceil(height / DES_HEIGHT) * DES_HEIGHTpadding_width = math.ceil(width / DES_WIDTH) * DES_WIDTH# 将padding图像与原始图像进行融合,使得原始padding_img = np.random.randint(0, 255, size=(padding_height, padding_width, 3)).astype(np.uint8)padding_img[0:height + 0, 0:width + 0] = srcimg = padding_img  # 读取彩色图像,图像的透明度(alpha通道)被忽略,默认参数;灰度图像;读取原始图像,包括alpha通道;可以用1,0,-1来表示sum_rows = img.shape[0]  # 高度sum_cols = img.shape[1]  # 宽度cols = DES_WIDTHrows = DES_HEIGHTsave_path = "切割后的小图片要保存在的目录/".format(cols, rows)  # 切割后的照片的存储路径static_rows = int(sum_rows / rows)static_cols = int(sum_cols / cols)filename = os.path.split(path_img)[1]for i in range(int(sum_cols / cols)):for j in range(int(sum_rows / rows)):cv2.imwrite(save_path + os.path.splitext(filename)[0] + '_' + str(j) + '_' + str(i) + os.path.splitext(filename)[1],img[j * rows:(j + 1) * rows, i * cols:(i + 1) * cols, :])# 合并分割图像,指定行列数
# merge_path:切割后的小图片所在路径
# num_of_cols:多少列
# num_of_rows:多少行
# target_path:合成后的目标图片保存路径
# file_name:合成后的文件名称
def merge_picture(merge_path, num_of_cols, num_of_rows, target_path, file_name):filename = os.listdir(merge_path)# 排除MacOS的.DS_Store文件if filename[0] == '.DS_Store':filename.remove('.DS_Store')full_path = os.path.join(merge_path, filename[0])shape = cv2.imread(full_path).shape  # 三通道的影像需把-1改成1cols = shape[1]rows = shape[0]channels = shape[2]dst = np.zeros((rows * num_of_rows, cols * num_of_cols, channels), np.uint8)for i in range(len(filename)):full_path = os.path.join(merge_path, filename[i])img = cv2.imread(full_path, -1)cols_th = int(full_path.split("_")[-1].split('.')[0])rows_th = int(full_path.split("_")[-2])roi = img[0:rows, 0:cols, :]dst[rows_th * rows:(rows_th + 1) * rows, cols_th * cols:(cols_th + 1) * cols, :] = roicv2.imwrite(target_path + "merge-" + file_name, dst)# 最终尺寸切割
# real_org_file_path:真正的原图所在的文件夹
# real_org_file_name:真正的原图的名称
# org_path:合成后的带有多余像素的图片所在路径
# fin_path:最终成品图保存的位置
# org_file_name:合成后带有多余像素的图片名字
# fin_file_name:最终成品图的名字
def cp(real_org_file_path, real_org_file_name, org_path, fin_path, org_file_name, fin_file_name):from PIL import Imageimg = Image.open(org_path+org_file_name)  # 打开chess.png文件,并赋值给imgorg_img = Image.open(real_org_file_path+real_org_file_name)region = img.crop((0, 0, org_img.width, org_img.height))  # 0,0表示要裁剪的位置的左上角坐标,w长 h宽。region.save(fin_path+fin_file_name)  # 将裁剪下来的图片保存# 加载图片列表
def round_read_file(file_path):image_name_list = []for file_name in os.listdir(file_path):# 排除MacOS的.DS_Store文件,Windows下不受影响。if file_name != '.DS_Store':print("加载图片:"+str(file_path)+str(file_name))image_name_list.append(str(file_name))print("总计加载图片数量" + str(len(image_name_list)))return image_name_list
# 主函数
if __name__ == '__main__':main_tmp_path = '切割后的小图片所保存的目录路径/'main_org_path = '真正的原图所在目录路径/'main_merge_path = '第一次合成之后带多余像素的图片所保存的路径/'main_fin_path = '最终成品所在的路径/'main_img_name_list = round_read_file(main_org_path)i = 1for main_file_name in main_img_name_list:print("第" + str(i) + "/" + str(len(main_img_name_list)) + "项," + "当前图片名称:" + main_file_name)qg(main_org_path+main_file_name)print("第" + str(i) + "/" + str(len(main_img_name_list)) + "项,切割完成,当前col:"+str(static_cols)+",row:" + str(static_rows))#################################################可在此处添加对小图的处理,例如某些对图片尺寸有要求的API#################################################merge_picture(main_tmp_path, static_cols, static_rows, main_merge_path, main_file_name)print("第" + str(i) + "/" + str(len(main_img_name_list)) + "项,合并完成")cp(main_org_path, main_file_name, main_merge_path, main_fin_path, str("merge-" + main_file_name), main_file_name)print("第" + str(i) + "/" + str(len(main_img_name_list)) + "项,完成")static_rows = -1static_cols = -1i = i + 1print("done!!!!")

【Python+图片切割+图片合并】基于Python的图片批量切割与合并(保持原像素不变,不会出现像素大小不匹配、填充黑边的问题)相关推荐

  1. Dataset之图片数据增强:基于TF实现图片数据增强(原始的训练图片reshaped_image→数据增强→distorted_image(训练时直接使用))

    Dataset之图片数据增强:基于TF实现图片数据增强(原始的训练图片reshaped_image→数据增强→distorted_image(训练时直接使用)) 目录 数据增强步骤 数据增强实现代码 ...

  2. python画素描画_基于python实现把图片转换成素描

    这篇文章主要介绍了基于python实现把图片转换成素描,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 导语: 你是否还在为当时年少时没有选择自己的梦 ...

  3. 基于python的房地产数据分析_基于Python的数据分析

    转载 | CSDN 编辑 | 雷课小雷 下面来介绍一下基于Python的数据分析,主要介绍数据分析的概念.数据分析流程.Python优势.常用模块的用途以及使用Python进行数据分析的学习方法及步骤 ...

  4. python生成json接口_基于python的Flask框架写json接口并且结合eolinker进行接口测试

    一.前言 很多时候为了提高软件开发的效率,后端程序人员理想状态下应该编写程序测试接口供前端程序人员进行测试,以便前端的开发.笔者由于项目的需求近期尝试学习了一下测试接口的编写,以Python+Flas ...

  5. 如何用python制作动画_如何基于Python Matplotlib实现网格动画

    -1- 如果你对本文的代码感兴趣,可以去 Github (文末提供)里查看.第一次运行的时候会报一个错误(还没找到解决办法),不过只要再运行一次就正常了. 这篇文章虽然不是篇典型的数据科学类文章,不过 ...

  6. python语法元素测试_基于python全局设置id 自动化测试元素定位过程解析

    背景: 在自动化化测试过程中,不方便准确获取页面的元素,或者在重构过程中方法修改造成元素层级改变,因此通过设置id准备定位. 一.python准备工作: 功能:用自动化的方式进行批量处理. 比如,你想 ...

  7. python人脸识别库_基于Python的face_recognition库实现人脸识别

    Python Python开发 Python语言 基于Python的face_recognition库实现人脸识别 一.face_recognition库简介 face_recognition是Pyt ...

  8. python编程控制机器人_基于Python开发的微信图灵机器人

    在过去的几个月中,由于在新生群中回答问题费时费力,同时又有许多重复而又有固定答案的回答,我受到一些知乎文章的启发,维护了一个基于itchat的群聊机器人.从刚开始接入图灵机器人时只会尬聊的机器人,之后 ...

  9. python扫雷算法_如何基于Python实现自动扫雷

    这篇文章主要介绍了如何基于Python实现自动扫雷,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 自动扫雷一般分为两种,一种是读取内存数据,而另一种 ...

  10. python 游戏开发框架_Python开发 基于python实现坦克大战游戏

    这篇文章主要为大家详细介绍了基于python实现坦克大战游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 本文实例为大家分享了python实现坦克大战游戏的具体代码, ...

最新文章

  1. 计算机网络原理 大型实验,计算机网络原理实验 实验一
  2. Java代码判断数据库中某张表是否存在
  3. Thrift入门及Java实例演示
  4. 免密登录关闭_微信最新提醒:这个设置再不关闭,你的微信账号就能被别人“免密登录”!...
  5. IDEA配置tomcat部署web项目时没有artifacts
  6. Oracle跟踪文件trace文件
  7. 关系数据库第一第二第三范式
  8. chrome浏览器调试css
  9. Nachos操作系统实习-lab1
  10. c语言的算法必须要有输入输出,多选题: 1、计算机算法必须具备输入、输出和________等特性...
  11. LDC1314和LDC1312的使用
  12. 帮我妹一 jio 踹开了 C 语言的大门,从此学习的路上不再迷茫不再彷徨(史上最强 C语言学习路线)
  13. Rockcip Android多媒体框架 Codec2
  14. python 键盘输入负数_python输入负数
  15. 通信算法之九:4FSK调制解调仿真链路
  16. DirectX11入门篇
  17. vue2+element-ui创建顶部导航栏及下拉菜单
  18. 马斯克与贝索斯:世界上最有钱的两人展开太空大战
  19. pygame 键盘事件
  20. Oracle调优之看懂Oracle执行计划

热门文章

  1. 【观察】 “最难啃”的中国云ERP市场,NetSuite凭什么全面领跑?
  2. 地球正在变“秃”?数据告诉你真相
  3. 软件单元测试自动化,如何做好软件系统自动化测试?
  4. dpi与dp的关系_px、dp、sp、dpi之间的区别和转换
  5. stm32CubeMX的安装和点亮流水灯
  6. from math import *
  7. dct变换的主要优点有哪些_【WIX维克斯】CVT打滑/DCT顿挫? 变速箱新知识来了
  8. python调用excel的宏_Excel Python 调用Excel-ExcelVBA程序开发-ExcelHome技术论坛 -
  9. 【Matlab】【第7届数维杯B】疫情爆发后小区的核酸检测分组方案
  10. 社区团购小程序怎么盈利