本文可以看作是我的这篇博客(切割过程)的续集。
一、数据说明:
(1)原始大图片:6000*6000
(2)小图片:512*512,且相邻小图片之间的重叠率为50%
(3)根据切割的要求,原图共被分割为140个小图片,即10行14列。
二、还原思路
(1)先将每一行的小图片还原为一条完整的图片,如下图:
第一行分割得到的14个小图片:
第一行还原得到的完整图片:
(2)按照上述方法,将10行小图片全部还原成完整的图片:
第一行:
第二行:
第三行:
……
……
……
第十行:
(3)再将第一行到第十行的条状图片拼接为一个完整的大图片。
三、上代码
代码中的注释写的很清晰明了,希望可以帮助到小伙伴们!
import os
import sys
import re
import math
from shutil import copyfile
from PIL import Image
result="F:/Practice/merge.png"#用于存放最终合并生成的图像
#将image.png切块得到的140个小块,按着每一行为一个文件夹划分,也就是把每一行的14个小图片单独放在一个文件夹里
origin_path = 'F:/Practice/test02/Images_01_res/'
result_path= 'F:/Practice/merge_res/'
filelist = os.listdir(origin_path)
for i in range(len(filelist)):
fileName = filelist[i] # '1.png'
name=re.split('_',fileName)
f_cls=int(name[4])
fileClass = "image_row"+str(f_cls)
filePath = result_path + fileClass + '/'
src_fileName = origin_path + fileName
tar_fileName = filePath + fileName
if not os.path.exists(filePath):
os.makedirs(filePath)
copyfile(src_fileName,tar_fileName)
#定义水平连接函数
def join_horizontal(i,png1, png2, size):
img1, img2 = Image.open(png1), Image.open(png2)
size1, size2 = img1.size, img2.size # 获取两张图片的大小
loc1, loc2 = (0, 0), (size1[0]-size,0)
a=size1[0]+size2[0]-size
if a > 6000:
a=6000
loc1, loc2 = (0, 0), (5488,0)
joint = Image.new('RGB', (a, size1[1]))
joint.paste(img2, loc2)
joint.paste(img1, loc1)
joint.save('F:/Practice/rows/row{}.png'.format(i))
#定义竖直连接函数
def join_vertical(png1, png2, size):
img1, img2 = Image.open(png1), Image.open(png2)
size1, size2 = img1.size, img2.size # 获取两张图片的大小
loc1, loc2 = (0, 0), (0,size1[1]-size)
a=size1[1]+size2[1]-size
if a > 6000:
a=6000
loc1, loc2 = (0, 0), (0,5488)
joint = Image.new('RGB', (size1[0],a))
joint.paste(img2, loc2)
joint.paste(img1, loc1)
joint.save(result)
#定义开始执行水平连接的函数
def start(i,items, size, first_path=None):
# 当first为None时,默认将第一张图片设置为图片列表的第一张图片,第二张图片设置为图片列表的第二张
# 当这两张图片合成后,将图片列表的已经合成的图片元素移除
# 然后将合成的图片设置为第一张图片,将剩余的没有合成的图片列表继续操作
# 当first_path不为None,将第一张图片设置为first_path,第二张图片设置为传进来的列表的第一个元素
# 合成之后,将刚刚使用的列表的元素删除
# 最后递归函数,直到列表为空
try:
if not first_path:
path1, path2 = items[0], items[1]
join_horizontal(i,path1, path2, size)
items.remove(path1)
items.remove(path2)
return start(i,items, size, first_path='F:/Practice/rows/row{}.png'.format(i))
else:
path2 = items[0]
join_horizontal(i,first_path, path2, size)
items.remove(path2)
return start(i,items, size, first_path='F:/Practice/rows/row{}.png'.format(i))
except:
pass
#定义开始执行竖直连接的函数
def ver_start(items, size, first_path=None):
try:
if not first_path:
path1, path2 = items[0], items[1]
join_vertical(path1, path2, size)
items.remove(path1)
items.remove(path2)
return ver_start(items, size, first_path=result)
else:
path2 = items[0]
join_vertical(first_path, path2, size)
items.remove(path2)
return ver_start(items, size, first_path=result)
except:
pass
#定义抓取path路径下所有文件的函数
def getAllImg(path):
result = []
filelist = os.listdir(path)
for file in filelist:
if os.path.isfile(os.path.join(path, file)):
if file.split('.')[1] in ('jpg', 'png'):
result.append(os.path.join(path, file))
return result
#在result文件夹下,创建一个image_rows文件夹,用于存放合并生成的每一行图片
rows_path= 'F:/Practice/rows'
if not os.path.exists(rows_path):
os.makedirs(rows_path)
# #在result文件夹下,创建一个label_rows文件夹,用于存放合并生成的每一行图片
# rows_path= 'F:/Practice/test_01/result/label_rows'
# if not os.path.exists(rows_path):
# os.makedirs(rows_path)
#将每一个row[i]文件夹下的小块水平合并成完整的一行图片,合并的结果存放在上一步创建的image_rows文件夹下
if __name__ == '__main__':
for i in range(1,13):
path='F:/Practice/row_dirs/image_row{}/'.format(i)
s = getAllImg(path)
# print(s)
s.sort(key=lambda x:int(x[51:-4]))
start(i,s, 0)
#将rows文件夹下存放的合成得到的每一行图片,竖直合并成完整的图像
if __name__ == '__main__':
path1="F:/Practice/rows/"
s1=getAllImg(path1)
s1.sort(key=lambda x:int(x[20:-4]))
# print(s1)
ver_start(s1, 0)
print('最后图片尺寸--->', Image.open(result).size)
四、总结
相信各位小伙伴在了解了合并的思路之后,能够很轻松的看懂代码。我的做法并不是按照小图片的文件名所对应的位置来进行的,我的思路比较简单粗暴。如果小伙伴们有什么问题,欢迎私信交流!