如何使用 os.walk 和 PIL 将编辑后的图像保存在新目录中,但子目录与原始源中的子目录相同?

问题描述 投票:0回答:1

我正在尝试使用 PIL 编辑指定目录(和子目录)内的所有图像,然后将编辑后的版本保存在不同的位置但在相同的子目录结构下。

即。输入:

Root directory
|
|---------Subdir 1
|           |---Image_1
|           |---Image_2
|           |---Image_3
|
|---------Subdir 2
|           |---Image_1
|           |---Image_2

And Output:
{Specified directory}
|
|---------Subdir 1
|           |---Edited_Image_1
|           |---Edited_Image_2
|           |---Edited_Image_3
|
|---------Subdir 2
|           |---Edited_Image_1
|           |---Edited_Image_2

子目录共享相同的名称,并在 os.walk 运行时创建。

我已将其构建为一个函数,以便稍后可以在 Linux 终端中运行它,并在调用该函数时更改选项。

from PIL import Image, ImageDraw, ImageOps
import os
from os.path import isfile, join

def editimage(image_directory="image_directory",
               version="B", #Specify which version of ImageDraw edit to do
               resize=False, #choose whether or not to resize image
               new_size=(800,428), #choose new size
               output_directory="output_directory"):

    for directory, subdirs, files in os.walk(image_directory):
        for dirname in subdirs:
            if not os.path.exists(output_directory + dirname):
                os.mkdir(output_directory + image_directory + dirname) #This does exactly what I want it to do

    for directory, subdirs, files in os.walk(image_directory):
        for f in files:
            if f.endswith('.JPG'):
                img = Image.open(directory + f)
                draw= ImageDraw.Draw(img)
                if version=="A":
                    draw.ellipse((1823, 1472, 2033, 1536), fill = (0,0,0), outline=None) 
                    draw.rectangle((0, 0, 2048, 32), fill = (0,0,0), outline=None) 
                    draw.rectangle((0, 1504, 2048, 1536), fill = (0,0,0), outline=None) 
                    img=ImageOps.pad(img, size=(2731,1536), color="grey")
                elif version=="B":
                    draw.rectangle((0, 1231, 2304, 1296), fill = (0,0,0), outline=None)
                if resize==True:
                    img = img.resize(new_size)
                else:
                    pass
                img.save(output_directory + "/" + f + ".png")

这会让用户输入:

editimage("Path/to/input/", version="A", resize= False, output_directory="Path/to/output/")

我尝试使用

img.save(output_directory + subdirs + ".png"
或为此创建一个变量,但 Python 返回:
TypeError: can only concatenate list (not "str") to list
,或者以其他方式希望输入目录位于输出目录中。它似乎并没有遍历每个子目录。

我以前用过

    imagelist = [join(directory, f)
                 for directory, subdirs, files in os.walk(image_directory)
                 for f in files
                 if isfile
                 if f.endswith('.JPG')]

    for f in imagelist:
        img = Image.open(f) #etc..

构建读取和编辑图像,但是

img.save(f)
保留整个路径并且无法将图像保存到新位置。

函数的其余部分工作完美,如果我删除 img.save 行中的 output_directory 参数,它将覆盖原始目录(和子目录)中的图像。在意识到输出目录没有被使用之前我没有遇到任何问题。

因为版本A组图像在文件夹之间没有唯一命名,所以我需要能够重建目录路径。

我该如何解决这个问题? 谢谢!

python image python-imaging-library subdirectory os.walk
1个回答
0
投票

下面的函数将为带注释的图像创建一个新目录,其树结构与输入目录相同。尽管您询问如何使用

pathlib
,我还是使用了核心 Python 库中的
os.walk()
。我喜欢它的面向对象方法,并发现代码更干净。 PEP248 提供了有关 pathlib 背后原理的更多详细信息。

from pathlib import Path

from PIL import Image, ImageDraw


def editimage(
    image_directory="image_directory",
    version="B",  # Specify which version of ImageDraw edit to do
    resize=False,  # choose whether or not to resize image
    new_size=(800, 428),  # choose new size
    output_directory="output_directory",
):
    for jpg_file in image_directory.rglob("*.jpg"):
        # Translate the input file path to the corresponding output file_path
        relative_path = jpg_file.relative_to(image_directory)
        output_file_path = output_directory / relative_path

        # Create the output directory if it doesn't exist
        output_file_path.parent.mkdir(parents=True, exist_ok=True)

        # Annotate the image and save it (simplified example)
        with Image.open(jpg_file) as img:
            draw = ImageDraw.Draw(img)
            draw.ellipse((0, 0, 300, 300), fill=(255, 0, 0), outline=None)
            img.save(output_file_path)


editimage(
    image_directory=Path("Path/to/input/"),
    version="A",
    resize=False,
    output_directory=Path("Path/to/output/"),
)
© www.soinside.com 2019 - 2024. All rights reserved.