在 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
为您订购。这可能会导致问题,因为无法保证列表将按字母顺序排列。
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.jpg
、frame1010.jpg
).如果它们被零填充,即使按字符串排序 (frame0101.jpg
、frame0102.jpg
、...、frame1010.jpg
),您也可以获得正确的顺序。
解决方法是从文件名中提取帧编号,将它们转换为整数,并根据此编号对文件名进行排序。实现此目的的最简单方法是:
sorted_images = sorted(images, key=lambda x:int(x[5:-4]))
其中 5 是前缀 frame
的长度,-4 是 .jpg
的长度,我希望从文件名中删除前缀和后缀。查看 sorted
的 python slicing and documentation of the key parameter 了解更多信息。
我需要根据 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
为您订购。这可能会导致问题,因为无法保证列表将按字母顺序排列。
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.jpg
、frame1010.jpg
).如果它们被零填充,即使按字符串排序 (frame0101.jpg
、frame0102.jpg
、...、frame1010.jpg
),您也可以获得正确的顺序。
解决方法是从文件名中提取帧编号,将它们转换为整数,并根据此编号对文件名进行排序。实现此目的的最简单方法是:
sorted_images = sorted(images, key=lambda x:int(x[5:-4]))
其中 5 是前缀 frame
的长度,-4 是 .jpg
的长度,我希望从文件名中删除前缀和后缀。查看 sorted
的 python slicing and documentation of the key parameter 了解更多信息。