为什么这个 for 循环有一个 i 计数器,在 Python 上附加图像时从 1 跳到 10? PIL相关

Why does this for loop have an i counter that jumps from 1 to 10 when appending images on Python? PIL related

我在某个特定路径有以下图像:

0.png
1.png
2.png
3.png
4.png
5.png
6.png
7.png
8.png
9.png
10.png
11.png
12.png
13.png
14.png
15.png
16.png
17.png
18.png
19.png
20.png
21.png
22.png
23.png
24.png
25.png
26.png

我想使用以下程序(位于图像所在的相同特定路径)将这些图像转换为单个 gif 文件

from PIL import Image
import glob

# Create the frames
frames = []
imgs = glob.glob("*.png")
for i in imgs:
    new_frame = Image.open(i)
    frames.append(new_frame)
    print(i)

# Save into a GIF file that loops forever
frames[0].save('png_to_gif.gif', format='GIF',
               append_images=frames[1:],
               save_all=True,
               duration=160, loop=0)

在 运行 上面的程序之后我得到了这个输出:

0.png
1.png
10.png
11.png
12.png
13.png
14.png
15.png
16.png
17.png
18.png
19.png
2.png
20.png
21.png
22.png
23.png
24.png
25.png
26.png
3.png
4.png
5.png
6.png
7.png
8.png
9.png

我如何确保程序附加图像的顺序与它们的命名顺序相同?

计算机不是按字母顺序而是按字典顺序排序。

“10”<“2”,因为程序从左到右查看符号(首先将 1 与 2 进行比较,如果相等则停止并大喊 10 较小)。 这就是为什么我会那样跳。

如果每个文件都具有相同的长度(001.png、002.png 等)会更好。如果你不想这样做,你可以对它们进行排序,记住长度是至关重要的(首先检查长度,然后如果 number1 < number2)

您得到的文件名似乎是按字典顺序排列的,作为字符串。这就是为什么以小数字开头的较长字符串排在具有较大数字的较短字符串之前的原因。就像按字母顺序 ah 排在 b 前面一样。

您希望字符串的数字部分按数字排序,以便 2 排在 10 之前。为此,您需要应用自己的排序逻辑。

尝试这样的事情:

import re # put this at the top of the file

def keyfunc(filename):
    prefix, numeral, suffix = re.split(r'(\d+)', filename, maxsplit=1)
    return prefix, int(numeral), suffix

imgs = glob.glob("*.png")
for i in sorted(imgs, key=keyfunc):
    ...

另一种解决方案可能是将名称中只有一个数字的文件重命名为具有前导零。也就是说,1.png 应该变成 01.png 等等。这样,正在应用的排序(通过 glob.glob 或您的文件系统)将正确排序所有内容(因为 0210 之前正确排序,甚至按字典顺序)。

我决定以这种方式修改代码,它目前似乎可以工作,如果有一种方法可以创建一个数组来仅存储以 .png 结尾的文件名path, 欢迎光临:

from PIL import Image


# Create the frames
frames = []
imgs = ["0.png", "1.png", "2.png", "3.png", "4.png", "5.png", "6.png", "7.png", "8.png", "9.png", "10.png", "11.png", "12.png", "13.png", "14.png", "15.png", "16.png", "17.png", "18.png", "19.png", "20.png", "21.png", "22.png", "23.png", "24.png", "25.png", "26.png"]
for i in imgs:
    new_frame = Image.open(i)
    frames.append(new_frame)
    print(i)

# Save into a GIF file that loops forever
frames[0].save('png_to_gif.gif', format='GIF',
               append_images=frames[1:],
               save_all=True,
               duration=180, loop=0)