如何在一个文件夹中的多个图像中串联5个图像 [英] How to Concatenate 5 Images Out Of Multiple Images In a Folder
问题描述
我有一个包含多个图像的文件夹,可以说图像名称为----
I have a folder which has multiple images lets say images names are----
AB_1.jpg,AB_2.jpg,AB_3.jpg,AB_4.jpg,AB_5.jpg,AB_6.jpg,AB_7.jpg,AB_8.jpg,BC_1.jpg,BC_2.jpg,BC_3.jpg,CA_1.jpg,CA_2.jpg
AB_1.jpg, AB_2.jpg, AB_3.jpg, AB_4.jpg, AB_5.jpg, AB_6.jpg, AB_7.jpg, AB_8.jpg, BC_1.jpg, BC_2.jpg, BC_3.jpg, CA_1.jpg, CA_2.jpg
这里我的目标是将直到_5或小于_5的所有图像连接为一张图像....
Here my objective is to concatenate all the images till _5 or less than _5 as one image....
所以基本上我说的是-AB_1.jpg,AB_2.jpg,AB_3.jpg,AB_4.jpg,AB_5.jpg
So basically what I am saying is that--- AB_1.jpg, AB_2.jpg, AB_3.jpg, AB_4.jpg, AB_5.jpg
将垂直连接,文件名可以说是AB_Concat.jpg
will get concatenated vertically and file name lets say will be AB_Concat.jpg
_6,_7,_8被跳过是因为我们只希望将直到_5为止的图像串联为一个....
_6,_7,_8 are skipped because we want to concatenate only images till _5 as one....
类似地,BC_1.jpg,BC_2.jpg,BC_3.jpg
Similarly,, BC_1.jpg, BC_2.jpg, BC_3.jpg
将被垂直连接,文件名可以说是BC_Concat.jpg,因为您在这里可以看到BC_3是最后一个小于_5的文件,因此所有文件都将被垂直连接.....
will get concatenated vertically and file name lets say will be BC_Concat.jpg as you can see here BC_3 is last one which is less than _5 so all will be concatenated vertically.....
因此,如果有人对如何实现相同的想法有任何帮助,请帮助....
So if anyone have any idea on how to achieve the same please help....
这个问题与将两个图像串联在一起的问题不同,因为这里我们是根据图像中下划线之后的值来串联图像....
This question is not similar to the once where two images are concatenated since here we are concatenating images on the basis of value after underscore in a image....
这是我尝试过的事情---
This is something which I tried---
import cv2
import shutil
import numpy as np
import os
from PIL import Image
path = r"D:\split"
out = r"D:\concat_test"
os.makedirs(out,exist_ok=True)
imag_name =[]
imag_name1 = []
for img in os.listdir(path):
folder = img.rsplit("_",1)[0]
imag_name1.append((folder,img))
images = cv2.imread(os.path.join(path,img),0)
imag_name.append((folder,images))
# to create a folder for multiple images contain same name
for image,name in zip(imag_name,imag_name1):
if image[0] == name[0]:
folder_n = os.path.join(out,name[0])
final_fldr = os.path.join(folder_n,name[1])
os.makedirs(folder_n,exist_ok=True)
cv2.imwrite(final_fldr,image[1])
# to concatinate the images
for root,dirs,files in os.walk(out):
np_images = [cv2.imread(os.path.join(root,file),0) for file in files]
np_name = list(set([file.rsplit("_",1)[0] for file in files]))
if len(np_images) != 0:
print(np_name)
concat = cv2.vconcat(np_images)
concatinated_images = os.path.join(out,"concatinated_images")
os.makedirs(concatinated_images,exist_ok=True)
cv2.imwrite(os.path.join(concatinated_images,*np_name)+".tif",concat)
#to remove the unwanted folder
for remove_folder in os.listdir(out):
if remove_folder != "concatinated_images":
folders_to_remove = os.path.join(out,remove_folder)
shutil.rmtree(folders_to_remove)
'''
推荐答案
您的问题有很多活动内容,因此我将尝试解决所有这些问题.希望代码对您的用例有所帮助.
Your question has lots of moving parts, so I will attempt to address all of them. Hopefully the code helps with your use case.
下面的代码可以做到这一点:
The code below does this:
-
确定目录X中存在哪些图像
Determine what images exist in directory X
基于文件名对图像进行分组
Group images based on file name
创建一个临时目录来存储基于组的图像.此目录将被自动删除.
Create a temporary directory to store images based on group. This directory will be removed automatically.
将本地文件复制到临时目录
Copy local files to temporary directory
将文件分成块(最多5个文件)
Chunk the files into blocks (5 files max)
将这些卡盘合并到带有边框分隔符的新图像中
Merge these chucks into a new image with a border separator
特别说明
在测试过程中,我注意到任何未包含要求的5个项目的列表均无法正确格式化.为了解决这个问题,我创建了一个blank_check.jpg,它使我可以正确格式化新图像.
During testing I noted that any list that did not contained the required 5 items would not format correctly. To fix this problem I created a blank_check.jpg, which allowed me to format the new image correctly.
import os
import shutil
import tempfile
import itertools
from PIL import Image
from PIL import ImageOps
def create_temp_directory(name):
"""
This function create a temporary directory, which will
be used to store files based on specific parts of a filename.
:param name:
:return:
"""
temp_dir = tempfile.TemporaryDirectory(suffix=None, prefix=f'temp_directory_{name}', dir=None)
return temp_dir
def divide_list_into_chunks(input_list, len_of_chunk):
"""
This function will divide a list into chunks.
:param input_list:
:param len_of_chunk:
:return:
"""
for i in range(0, len(input_list), len_of_chunk):
yield input_list[i:i + len_of_chunk]
def add_blank_checks(input_list, temp_dir):
"""
:param input_list:
:param temp_dir:
:return:
"""
number_of_images = (5 - len(input_list))
for _ in range(number_of_images):
shutil.copy(f'blank_check.jpg', f'{temp_dir.name}/blank_check.jpg')
input_list.append(f'{temp_dir.name}/blank_check.jpg')
return input_list
def merge_images_vertically(list_of_images, file_name):
"""
This function is designed to merge images vertically
:param list_of_images: current list of images to process
:param file_name: file name for the new image
:return:
"""
# open images using Pillow
images = [Image.open(im) for im in list_of_images]
# Create separate lists to store the heights and widths
# of the images
widths, heights = zip(*(i.size for i in images))
width_of_new_image = min(widths)
height_of_new_image = sum(heights)
# create a new output image
new_im = Image.new('RGB', (width_of_new_image, height_of_new_image))
new_pos = 0
counter = 0
for im in images:
if counter == 0:
new_im.paste(im, (0, new_pos))
new_pos += im.size[1]
counter += 1
else:
color = "black"
border = (0, 10, 0, 0)
img_with_border = ImageOps.expand(im, border=border, fill=color)
new_im.paste(img_with_border, (0, new_pos))
new_pos += im.size[1]
new_im.save(f'{file_name}', "JPEG", quality=75, optimize=True, progressive=True)
return
image_directory = "sample_images"
image_directory_abspath = os.path.abspath(image_directory)
images = os.listdir(image_directory_abspath)
accepted_extensions = ('.bmp', '.gif', '.jpg', '.jpeg', '.png', '.svg', '.tiff')
valid_image_extensions = [im for im in images if im.endswith(accepted_extensions)]
image_groups = [list(g) for _, g in itertools.groupby(sorted(valid_image_extensions), lambda x: x[0:2])]
for image_group in image_groups:
count = 0
name_group = image_group[0][:2]
temp_directory = create_temp_directory(name_group)
image_list = [shutil.copy(f'{image_directory_abspath}/{item}', f'{temp_directory.name}/{item}') for item in image_group]
max_number_of_items = 5
chunks = list(divide_list_into_chunks(image_list, max_number_of_items))
for chunk in chunks:
count += 1
if len(chunk) == 5:
merge_images_vertically(chunk, f'{name_group}_merged_{count}.jpeg')
else:
new_checks = add_blank_checks(chunk, temp_directory)
merge_images_vertically(new_checks, f'{name_group}_merged_{count}.jpeg')
合并图像文件的样本
----------------------------------------
System information
----------------------------------------
Platform: macOS Catalina
Python: 3.8.0
Pillow: 8.0.1
----------------------------------------
这篇关于如何在一个文件夹中的多个图像中串联5个图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!