在 python 中创建视频时如何保留图像的顺序

How do I preserve the order of images while creating video in python

我需要根据 python 中的图像序列创建视频。我在网上发现这段代码工作正常,但我在 python 中读取图像时遇到了一个小问题。即使文件夹中的顺序没问题。 E.x frame100.jpg , frame101.jpg , frame102.jpg,....., frame1000, frame1001, .... 当我在循环中使用 python 阅读它们时,调试后我看到以下内容 'frame100.jpg', 'frame1000.jpg', 'frame1001.jpg', 'frame1002.jpg',.....,frame101,frame1010,frame1011....

这是代码

def images_to_video():

image_folder = 'data_out'


images = [img for img in os.listdir(image_folder) if img.endswith(".jpg")]
frame = cv2.imread(os.path.join(image_folder, images[0]))
height, width, layers = frame.shape

video = cv2.VideoWriter('project.avi',cv2.VideoWriter_fourcc(*'DIVX'), 15, (width,height))


for image in images:
    video.write(cv2.imread(os.path.join(image_folder, image)))


cv2.destroyAllWindows()
video.release()

您需要使用知道如何对数字进行排序的自然排序对文件名进行排序:

import re

def natural_sort_key(s, _nsre=re.compile('([0-9]+)')):
    return [
        int(text)
        if text.isdigit() else text.lower()
        for text in _nsre.split(s)]

sorted_images = sorted(images, key=natural_sort_key)

您并未明确订购相框,而是依赖 os.listdir 为您订购。这可能会导致问题,因为无法保证列表将按字母顺序排列。

参考:os.listdir() Documentation

Return a list containing the names of the entries in the directory given by path. The list is in arbitrary order

解决方案 1

在处理之前明确排序您的列表,例如

images = images.sort()

for image in images.sort():

但是,要执行此操作,您必须先修改文件的名称,否则它会像您描述的那样排序为 100 > 1001 > 1002 ... 101 > 1010。为此,您可以例如在小于 1000 的文件名前加零:

images = [img if len(img)==13 else img[:7] + "0" + img[-7:] for img in images]

解决方案 2

如果您确定所有文件的格式都是"frame + number + .jpg"那么您可以这样做:

images = ["frame" + str(i) + ".jpg" for i in range(100, 1234)] ## replace 1234 with (last frame number + 1)

首先,文件夹中的文件在任何方面都不 "ordered" OS 级别(至少在我所知道的最流行的操作系统中)。如果您在某些文件浏览器中看到它们 "ordered",它纯粹是由文件浏览器应用程序本身完成的 (finder/file explorer/etc),但 python 不使用它。

其次,如果您阅读 os.listdir 的文档,它会明确指定以任意顺序返回文件。你应该自己订购。

第三,您的文件命名时没有补零。这意味着如果您在 alphabetical order 中对文件名进行排序(这是 python 中字符串的默认设置),您将获得上面指定的顺序(frame101.jpgframe1010.jpg ).如果它们被零填充,即使按字符串排序 (frame0101.jpgframe0102.jpg、...、frame1010.jpg),您也可以获得正确的顺序。

解决方法是从文件名中提取帧编号,将它们转换为整数,并根据此编号对文件名进行排序。实现此目的的最简单方法是:

sorted_images = sorted(images, key=lambda x:int(x[5:-4]))

其中 5 是前缀 frame 的长度,-4 是 .jpg 的长度,我希望从文件名中删除前缀和后缀。查看 sortedpython slicing and documentation of the key parameter 了解更多信息。