将所有 tiff 图像合并为一个图像
Combine all tiff images into one single image
我在一个文件夹中有 15 个图块或 tiff 文件,我想将它作为一个文件与所有图像合并为一个 tiff 图像。所有图块都应拼接为单个 tiff 图像。我该怎么做?
到目前为止我尝试了什么?
import imageio
import os
path = "path/to/dir"
image_path_list = os.listdir(path)
with imageio.get_writer("new_image.tif") as new_image:
for image_path in image_path_list:
image = imageio.imread(path+image_path)
new_image.append_data(image)
这将作为单独的图像保存在 tiff 文件中。我想将所有图片拼接在一起并保存如下:
1,2,3...,15 代表方块。需要拼接成单张图片
读取列表中的所有图像。使用两个嵌套的 for 循环遍历此列表。一个在 3 个范围内,一个在 5 个范围内。使用 numpy.hstack()
和 numpy.vstack()
制作最终的 3x5 图像,假设每个平铺图像的大小相同。
从你的评论看来,你准备考虑一个非Python的解决方案,所以我在终端中使用ImageMagick来拼接15张图片如下:
magick montage -tile 3x -geometry +0+0 09*tif result.tif
为了演示如何放置 5 张图片而不是 3 张图片,添加不同的背景并以不同方式影响水平和垂直间距,这里是一个变体:
magick montage -background magenta -tile 5x -geometry +5+15 09*tif result.tif
仅供参考,我制作了 15 个随机着色的方块:
for x in {a..o} ; do magick xc: +noise random -scale 80x50\! 09$x.tif ; done
给定一个目录,其中包含 15 张相同大小的图像
使用 PIL(枕头),我得到了:
from PIL import Image
import os
path_to_file ='tiff-files'
images = []
for i in os.listdir(path_to_file):
with Image.open(path_to_file+'/'+i) as im:
images.append(im.copy())
new_image = Image.new(images[0].mode, (images[0].size[0]*3,images[0].size[1]*5))
new_image.paste(images[0])
new_image.paste(images[1],(images[0].size[0]*1,0))
new_image.paste(images[2],(images[0].size[0]*2,0))
new_image.paste(images[3],(0,images[0].size[1]*1))
new_image.paste(images[4],(images[0].size[0]*1,images[0].size[1]*1))
new_image.paste(images[5],(images[0].size[0]*2,images[0].size[1]*1))
new_image.paste(images[6],(0,images[0].size[1]*2))
new_image.paste(images[7],(images[0].size[0]*1,images[0].size[1]*2))
new_image.paste(images[8],(images[0].size[0]*2,images[0].size[1]*2))
new_image.paste(images[9],(0,images[0].size[1]*3))
new_image.paste(images[10],(images[0].size[0]*1,images[0].size[1]*3))
new_image.paste(images[11],(images[0].size[0]*2,images[0].size[1]*3))
new_image.paste(images[12],(0,images[0].size[1]*4))
new_image.paste(images[13],(images[0].size[0]*1,images[0].size[1]*4))
new_image.paste(images[14],(images[0].size[0]*2,images[0].size[1]*4))
new_image.show()
让我知道它是否有效......
Mark Setchell 在此建议新版本后,希望更好
from PIL import Image
import os
path_to_file ='tiff-files'
def stich_tile(path_to_file, xx , yy):
images = []
for i in os.listdir(path_to_file):
images.append(i)
if len(images) >= xx*yy:
pass
else:
raise ValueError('not enough images in path_to_file !!!!!!!!!!!')
sq_x = xx
sq_y = yy
img_x = (Image.open(path_to_file+'/'+images[0]).size[0])
img_y = (Image.open(path_to_file+'/'+images[0]).size[1])
img_mode = (Image.open(path_to_file+'/'+images[0]).mode)
new_image = Image.new(img_mode, (img_x*sq_x, img_y*sq_y))
x = 0
y = 0
cnt = 0
for i in images:
with Image.open(path_to_file+'/'+i) as img:
new_image.paste(img, (x,y))
cnt += 1
x += img_x
if cnt == sq_x:
x = 0
y += img_y
cnt = 0
else:
pass
return new_image
stich_tile(path_to_file, 3, 5).show()
并且更多地按照
的思路思考
import numpy as np
from PIL import Image
import os
# path_to_file ='tiff-files'
path_to_file ='tiff-files2'
# path_to_file ='tiff-files3'
image = []
for i in os.listdir(path_to_file):
with Image.open(path_to_file+'/'+i) as im:
image.append(im.copy())
w, h = image[0].size
new_image = np.zeros((4 * h, 3 * w)).astype('uint8')
col = 0
row = -1
for i, img in enumerate(image):
if not i % 3 :
row += 1
col = 0
img = np.array(img)
new_image[row * h: (row + 1) * h, col * w: (col + 1) * w] = img
col += 1
image_pillow = Image.fromarray(new_image, mode = 'L')
image_pillow.save('prova.tif', mode = 'L')
image_pillow.show()
使用 .tif 图像灰度 8 位进行测试
修改为 RGB 等添加 3 个通道:
new_image = np.zeros((3 * h, 3 * w,3)).astype('uint8')
new_image[row * h: (row + 1) * h,col * w: (col + 1) * w,:] = img
再次将最后一个示例作为 8 位灰度图像的函数:
import numpy as np
from PIL import Image
import os
path_to_file ='tiff-files'
# path_to_file ='tiff-files2'
# path_to_file ='tiff-files3'
# path_to_file ='tiff-files5'
def stich_img(path_to_file, x , y):
image = []
for i in os.listdir(path_to_file):
image.append(path_to_file+'/'+i)
print(image)
if len(image) >= x*y:
pass
else:
# raise ValueError('not enough images in path_to_file !!!!!!!!!!!')
raise ValueError('EXCEPTION not enough images in path_to_file !!!!!!!!!!!', x*y ,'images needed : ', len(image),'images present !!!')
image = image[:x*y] #-----> riduce lista immagini al numero richiesto
with Image.open(image[0]) as img0:
w, h = img0.size
# new_image = np.zeros((4 * h, 3 * w)).astype('uint8')
new_image = np.zeros((y * h, x * w)).astype('uint8')
col = 0
row = -1
for i, imgs in enumerate(image):
with Image.open(imgs) as img:
if not i % x :
row += 1
col = 0
img = np.array(img)
new_image[row * h: (row + 1) * h, col * w: (col + 1) * w] = img
col += 1
image_pillow = Image.fromarray(new_image, mode = 'L')
return image_pillow
img_stiched = stich_img(path_to_file, 3,5)
# img_stiched.save('prova.tif', mode = 'L')
img_stiched.show()
使用 numpy:
此脚本接受图像生成器(以更快地处理大图像)。它不会提前检查它们的大小。如果图像高度不适合行高或者行的宽度不同,它将失败。
#!/usr/bin/env python3
import numpy as np
from imageio import imread, imwrite
from pathlib import Path
def tile_images(images, cols):
"""Tile images of same size to grid with given number of columns.
Args:
images (collection of ndarrays)
cols (int): number of colums
Returns:
ndarray: stitched image
"""
images = iter(images)
first = True
rows = []
i = 0
while True:
try:
im = next(images)
print(f"add image, shape: {im.shape}, type: {im.dtype}")
except StopIteration:
if first:
break
else:
im = np.zeros_like(im) # black background
if first:
row = im # start next row
first = False
else:
row = np.concatenate((row, im), axis=1) # append to row
i += 1
if not i % cols:
print(f"row done, shape: {row.shape}")
rows.append(row) # finished row
first = True
tiled = np.concatenate(rows) # stitch rows
return tiled
def main():
images = (imread(f) for f in Path().glob("*.*") if f.suffix in (".jpg", ".png") if f.name != "new.png")
new = tile_images(images, cols=3)
imwrite("new.png", new)
def test():
im1 = np.arange(65536).reshape(256,256)
im2 = np.arange(65536/2).reshape(128,256)
images = [im1,im1,im1,im2,im2,im2]
# works
new = tile_images(images, 3)
imwrite("new.png", new)
# failes
new = tile_images(images, 2)
imwrite("new2.png", new)
if __name__ == "__main__":
main()
# test()
我在一个文件夹中有 15 个图块或 tiff 文件,我想将它作为一个文件与所有图像合并为一个 tiff 图像。所有图块都应拼接为单个 tiff 图像。我该怎么做?
到目前为止我尝试了什么?
import imageio
import os
path = "path/to/dir"
image_path_list = os.listdir(path)
with imageio.get_writer("new_image.tif") as new_image:
for image_path in image_path_list:
image = imageio.imread(path+image_path)
new_image.append_data(image)
这将作为单独的图像保存在 tiff 文件中。我想将所有图片拼接在一起并保存如下:
1,2,3...,15 代表方块。需要拼接成单张图片
读取列表中的所有图像。使用两个嵌套的 for 循环遍历此列表。一个在 3 个范围内,一个在 5 个范围内。使用 numpy.hstack()
和 numpy.vstack()
制作最终的 3x5 图像,假设每个平铺图像的大小相同。
从你的评论看来,你准备考虑一个非Python的解决方案,所以我在终端中使用ImageMagick来拼接15张图片如下:
magick montage -tile 3x -geometry +0+0 09*tif result.tif
为了演示如何放置 5 张图片而不是 3 张图片,添加不同的背景并以不同方式影响水平和垂直间距,这里是一个变体:
magick montage -background magenta -tile 5x -geometry +5+15 09*tif result.tif
仅供参考,我制作了 15 个随机着色的方块:
for x in {a..o} ; do magick xc: +noise random -scale 80x50\! 09$x.tif ; done
给定一个目录,其中包含 15 张相同大小的图像
使用 PIL(枕头),我得到了:
from PIL import Image
import os
path_to_file ='tiff-files'
images = []
for i in os.listdir(path_to_file):
with Image.open(path_to_file+'/'+i) as im:
images.append(im.copy())
new_image = Image.new(images[0].mode, (images[0].size[0]*3,images[0].size[1]*5))
new_image.paste(images[0])
new_image.paste(images[1],(images[0].size[0]*1,0))
new_image.paste(images[2],(images[0].size[0]*2,0))
new_image.paste(images[3],(0,images[0].size[1]*1))
new_image.paste(images[4],(images[0].size[0]*1,images[0].size[1]*1))
new_image.paste(images[5],(images[0].size[0]*2,images[0].size[1]*1))
new_image.paste(images[6],(0,images[0].size[1]*2))
new_image.paste(images[7],(images[0].size[0]*1,images[0].size[1]*2))
new_image.paste(images[8],(images[0].size[0]*2,images[0].size[1]*2))
new_image.paste(images[9],(0,images[0].size[1]*3))
new_image.paste(images[10],(images[0].size[0]*1,images[0].size[1]*3))
new_image.paste(images[11],(images[0].size[0]*2,images[0].size[1]*3))
new_image.paste(images[12],(0,images[0].size[1]*4))
new_image.paste(images[13],(images[0].size[0]*1,images[0].size[1]*4))
new_image.paste(images[14],(images[0].size[0]*2,images[0].size[1]*4))
new_image.show()
让我知道它是否有效......
Mark Setchell 在此建议新版本后,希望更好
from PIL import Image
import os
path_to_file ='tiff-files'
def stich_tile(path_to_file, xx , yy):
images = []
for i in os.listdir(path_to_file):
images.append(i)
if len(images) >= xx*yy:
pass
else:
raise ValueError('not enough images in path_to_file !!!!!!!!!!!')
sq_x = xx
sq_y = yy
img_x = (Image.open(path_to_file+'/'+images[0]).size[0])
img_y = (Image.open(path_to_file+'/'+images[0]).size[1])
img_mode = (Image.open(path_to_file+'/'+images[0]).mode)
new_image = Image.new(img_mode, (img_x*sq_x, img_y*sq_y))
x = 0
y = 0
cnt = 0
for i in images:
with Image.open(path_to_file+'/'+i) as img:
new_image.paste(img, (x,y))
cnt += 1
x += img_x
if cnt == sq_x:
x = 0
y += img_y
cnt = 0
else:
pass
return new_image
stich_tile(path_to_file, 3, 5).show()
并且更多地按照
import numpy as np
from PIL import Image
import os
# path_to_file ='tiff-files'
path_to_file ='tiff-files2'
# path_to_file ='tiff-files3'
image = []
for i in os.listdir(path_to_file):
with Image.open(path_to_file+'/'+i) as im:
image.append(im.copy())
w, h = image[0].size
new_image = np.zeros((4 * h, 3 * w)).astype('uint8')
col = 0
row = -1
for i, img in enumerate(image):
if not i % 3 :
row += 1
col = 0
img = np.array(img)
new_image[row * h: (row + 1) * h, col * w: (col + 1) * w] = img
col += 1
image_pillow = Image.fromarray(new_image, mode = 'L')
image_pillow.save('prova.tif', mode = 'L')
image_pillow.show()
使用 .tif 图像灰度 8 位进行测试
修改为 RGB 等添加 3 个通道:
new_image = np.zeros((3 * h, 3 * w,3)).astype('uint8')
new_image[row * h: (row + 1) * h,col * w: (col + 1) * w,:] = img
再次将最后一个示例作为 8 位灰度图像的函数:
import numpy as np
from PIL import Image
import os
path_to_file ='tiff-files'
# path_to_file ='tiff-files2'
# path_to_file ='tiff-files3'
# path_to_file ='tiff-files5'
def stich_img(path_to_file, x , y):
image = []
for i in os.listdir(path_to_file):
image.append(path_to_file+'/'+i)
print(image)
if len(image) >= x*y:
pass
else:
# raise ValueError('not enough images in path_to_file !!!!!!!!!!!')
raise ValueError('EXCEPTION not enough images in path_to_file !!!!!!!!!!!', x*y ,'images needed : ', len(image),'images present !!!')
image = image[:x*y] #-----> riduce lista immagini al numero richiesto
with Image.open(image[0]) as img0:
w, h = img0.size
# new_image = np.zeros((4 * h, 3 * w)).astype('uint8')
new_image = np.zeros((y * h, x * w)).astype('uint8')
col = 0
row = -1
for i, imgs in enumerate(image):
with Image.open(imgs) as img:
if not i % x :
row += 1
col = 0
img = np.array(img)
new_image[row * h: (row + 1) * h, col * w: (col + 1) * w] = img
col += 1
image_pillow = Image.fromarray(new_image, mode = 'L')
return image_pillow
img_stiched = stich_img(path_to_file, 3,5)
# img_stiched.save('prova.tif', mode = 'L')
img_stiched.show()
使用 numpy: 此脚本接受图像生成器(以更快地处理大图像)。它不会提前检查它们的大小。如果图像高度不适合行高或者行的宽度不同,它将失败。
#!/usr/bin/env python3
import numpy as np
from imageio import imread, imwrite
from pathlib import Path
def tile_images(images, cols):
"""Tile images of same size to grid with given number of columns.
Args:
images (collection of ndarrays)
cols (int): number of colums
Returns:
ndarray: stitched image
"""
images = iter(images)
first = True
rows = []
i = 0
while True:
try:
im = next(images)
print(f"add image, shape: {im.shape}, type: {im.dtype}")
except StopIteration:
if first:
break
else:
im = np.zeros_like(im) # black background
if first:
row = im # start next row
first = False
else:
row = np.concatenate((row, im), axis=1) # append to row
i += 1
if not i % cols:
print(f"row done, shape: {row.shape}")
rows.append(row) # finished row
first = True
tiled = np.concatenate(rows) # stitch rows
return tiled
def main():
images = (imread(f) for f in Path().glob("*.*") if f.suffix in (".jpg", ".png") if f.name != "new.png")
new = tile_images(images, cols=3)
imwrite("new.png", new)
def test():
im1 = np.arange(65536).reshape(256,256)
im2 = np.arange(65536/2).reshape(128,256)
images = [im1,im1,im1,im2,im2,im2]
# works
new = tile_images(images, 3)
imwrite("new.png", new)
# failes
new = tile_images(images, 2)
imwrite("new2.png", new)
if __name__ == "__main__":
main()
# test()