如何在一个文件夹中的多个图像中串联5个图像 [英] How to Concatenate 5 Images Out Of Multiple Images In a Folder

查看:70
本文介绍了如何在一个文件夹中的多个图像中串联5个图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含多个图像的文件夹,可以说图像名称为----

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:

  1. 确定目录X中存在哪些图像

  1. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆