2021-08-30-同事需求--将多个文件夹内的图片合成视频

此篇博客介绍了如何使用Python脚本批量处理位于多层文件夹中的图片,通过复制和替换操作,将图片转换为每秒切换一次的简单视频,适合对视频效果要求不高的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 需求:

在一个大文件夹里(第一层),有很多小文件夹(第二层),每个小文件夹里有很多相同像素尺寸的图片,需要合成视频,不需要那么花里胡哨的,只是简单的视频即可,哪怕只有简单的图片切换,一个图片显示一秒钟就可以 

 

 代码粗狂实现如下:写的过程中很多不知道,就写了很多试错的备注,如果不喜欢,最下面有一个简洁版的,可以直接复制

import os
import cv2
import shutil
from ntpath import join
from tkinter import messagebox
from tkinter import filedialog
from pypinyin import lazy_pinyin  # 用于汉字转英文
from os.path import join as path_join
# import numpy  # cv2无法识别中文,需要numpy,结果很明显失败了,可以显示了,但是无法写入视频文件,算了,还是老老实实改英文吧

# 编译环境:Python3.9,Win10系统
# 需要额外安装的库:cv2、pypinyin
# 根据原图的数量,进行批量复制出来,从而达到延迟的效果
# 请选择文件夹的之前,尽量将文件放在 D、E等盘符,防止用户名是中文的情况,会报错

messagebox.showinfo('友情提示!','请选择文件夹的之前,尽量将文件放在 D、E等盘符,\n\n 防止用户名是中文的情况,会报错!!!')
messagebox.showerror('友情提示!','现在您确定您的文件夹路径是没有中文的是么? \n\n 我指的是第一层文件夹之前的路径')
messagebox.showwarning('友情提示!','如果你确定没有问题,OK,你可以继续了,\n\n 如果异常,你现在还有最后一次机会停止程序!')

path = filedialog.askdirectory()
# path = r'C:\Users\Administrator\Desktop\sts\图片'
path_new = str(path) + '1'

def rename_folder():
    for i in os.listdir(path_new):
        for k in os.listdir(path_join(path_new,i)):
            os.rename(path_join(path_new,i,k),path_join(path_new,i,k).replace('.png','.jpg'))
        for k in os.listdir(path_join(path_new,i)):
            os.rename(path_join(path_new,i,k),path_join(path_new,i,'_'.join(lazy_pinyin(k))))
        os.rename(path_join(path_new,i),path_join(path_new,'_'.join(lazy_pinyin(i))))
    os.rename(path_new,'_'.join(lazy_pinyin(path_new)))
    
    # return path_new
    print('_'.join(lazy_pinyin(path_new)))
    return '_'.join(lazy_pinyin(path_new))

def right_to_left_find(string,string_find):
    finally_num = string[::-1].find(string_find)+1 # 这里+1 是为了把搜索的字符也加上去
    # print(f'倒序之后的第一个出现的位置:{finally_num}')
    result = string[len(string)-finally_num:]
    # print(f'从右向左查找的结果为:{result}')
    return result

def copt_allfile():
    shutil.copytree(path,path_new) # copytree 可以递归里面所有文件,相当于是复制文件夹
    for i in os.listdir(path_new):
        k_value = 0
        for k in os.listdir(path_join(path_new,i)):
            if not os.path.isdir(path_join(path_new,i,k)):

                for j in range(30):
                # for j in range(1,30 * len(os.listdir(path_join(path_new,i))) + 1):
                    # print(path_join(i,k),' →→→ ',str(k_value) + right_to_left_find(k,'.'))
                    shutil.copy2(path_join(path_new,i,k),path_join(path_new,i,str(k_value) + right_to_left_find(k,'.')))
                    k_value += 1
                os.remove(path_join(path_new,i,k)) # 删除原来的图片

def creade_video(path_new): # 这里要加入一个形参,不然就会报错: local variable 'path_new' referenced before assignment  局部变量path_new在赋值前被引用
    path = path_new
    # 获取每个文件夹里面的第一个图片的路径, 用于后面获取尺寸使用
    for i in os.listdir(path):
        path_new = path_join(path,i)

        #获取一张图片的宽高作为视频的宽高
        # image = numpy.fromfile(path_join(path_new,os.listdir(path_new)[0]),dtype=numpy.uint8)
        # image=cv2.imdecode(image,-1)  # cv2无法识别中文,需要numpy 的 fromfile  然后使用 cv2的 imdecode 转码识别,,事实证明,图片是可以读取了,但是视频还是无法正常播放,还是老老实实改英文吧
        image=cv2.imread(path_join(path_new,os.listdir(path_new)[0]))

        cv2.imshow("new window", image)   #显示图片
        cv2.waitKey(1000) # 0或者不写参数,代表不关闭,写1000,代表1s后关闭

        image_info=image.shape
        height=image_info[0]
        width=image_info[1]
        size=(height,width)
        print(size)
        fps=30
        fourcc=cv2.VideoWriter_fourcc(*"mp4v")
        video = cv2.VideoWriter(path_join(path_new,'join_photo.mp4'), cv2.VideoWriter_fourcc(*"mp4v"), fps, (width,height)) #创建视频流对象-格式一

        # video = cv2.VideoWriter('ss.mp4', cv2.VideoWriter_fourcc('m', 'p', '4', 'v'), fps, (width,height)) #创建视频流对象-格式二
        """
        参数1 即将保存的文件路径
        参数2 VideoWriter_fourcc为视频编解码器
            fourcc意为四字符代码(Four-Character Codes),顾名思义,该编码由四个字符组成,下面是VideoWriter_fourcc对象一些常用的参数,注意:字符顺序不能弄混
            cv2.VideoWriter_fourcc('I', '4', '2', '0'),该参数是YUV编码类型,文件名后缀为.avi 
            cv2.VideoWriter_fourcc('P', 'I', 'M', 'I'),该参数是MPEG-1编码类型,文件名后缀为.avi 
            cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'),该参数是MPEG-4编码类型,文件名后缀为.avi 
            cv2.VideoWriter_fourcc('T', 'H', 'E', 'O'),该参数是Ogg Vorbis,文件名后缀为.ogv 
            cv2.VideoWriter_fourcc('F', 'L', 'V', '1'),该参数是Flash视频,文件名后缀为.flv
            cv2.VideoWriter_fourcc('m', 'p', '4', 'v')    文件名后缀为.mp4
        参数3 为帧播放速率
        参数4 (width,height)为视频帧大小
        """
        for i in range(len(os.listdir(path_new))):
            file_name = path_join(path_new,str(i) + '.jpg')
            print(file_name)
            image=cv2.imread(file_name)
            video.write(image)  # 向视频文件写入一帧--只有图像,没有声音

if __name__ == "__main__":
    copt_allfile()
    creade_video(rename_folder()) # 获取返回值

    # 写在最后的话,如果分辨率不同,那么在视频中,是无法加载出来的,就是根本看不到...
    # creade_video(path_new) # 获取返回值

如果你不喜欢上面太多废话,可以看看这里的代码,

都是一样的,去掉了试错的代码和注释

import os
import cv2
import shutil
from ntpath import join
from tkinter import messagebox
from tkinter import filedialog
from pypinyin import lazy_pinyin  # 用于汉字转英文
from os.path import join as path_join

# 编译环境:Python3.9,Win10系统
# 需要额外安装的库:cv2、pypinyin
# 根据原图的数量,进行批量复制出来,从而达到延迟的效果
# 请选择文件夹的之前,尽量将文件放在 D、E等盘符,防止用户名是中文的情况,会报错

messagebox.showinfo('友情提示!','请选择文件夹的之前,尽量将文件放在 D、E等盘符,\n\n 防止用户名是中文的情况,会报错!!!')
messagebox.showerror('友情提示!','现在您确定您的文件夹路径是没有中文的是么? \n\n 我指的是第一层文件夹之前的路径')
messagebox.showwarning('友情提示!','如果你确定没有问题,OK,你可以继续了,\n\n 如果异常,你现在还有最后一次机会停止程序!')
path = filedialog.askdirectory()
path_new = str(path) + '1'

def rename_folder():
    for i in os.listdir(path_new):
        for k in os.listdir(path_join(path_new,i)):
            os.rename(path_join(path_new,i,k),path_join(path_new,i,k).replace('.png','.jpg'))
        for k in os.listdir(path_join(path_new,i)):
            os.rename(path_join(path_new,i,k),path_join(path_new,i,'_'.join(lazy_pinyin(k))))
        os.rename(path_join(path_new,i),path_join(path_new,'_'.join(lazy_pinyin(i))))
    os.rename(path_new,'_'.join(lazy_pinyin(path_new)))
    return '_'.join(lazy_pinyin(path_new))

def right_to_left_find(string,string_find):
    finally_num = string[::-1].find(string_find)+1 # 这里+1 是为了把搜索的字符也加上去
    result = string[len(string)-finally_num:]
    return result

def copt_allfile():
    shutil.copytree(path,path_new) # copytree 可以递归里面所有文件,相当于是复制文件夹
    for i in os.listdir(path_new):
        k_value = 0
        for k in os.listdir(path_join(path_new,i)):
            if not os.path.isdir(path_join(path_new,i,k)):

                for j in range(30):
                    shutil.copy2(path_join(path_new,i,k),path_join(path_new,i,str(k_value) + right_to_left_find(k,'.')))
                    k_value += 1
                os.remove(path_join(path_new,i,k)) # 删除原来的图片

def creade_video(path_new): # 这里要加入一个形参,不然就会报错: local variable 'path_new' referenced before assignment  局部变量path_new在赋值前被引用
    path = path_new
    for i in os.listdir(path):
        path_new = path_join(path,i)
        image=cv2.imread(path_join(path_new,os.listdir(path_new)[0]))
        cv2.imshow("new window", image)   #显示图片
        cv2.waitKey(1000) # 0或者不写参数,代表不关闭,写1000,代表1s后关闭

        image_info=image.shape
        height=image_info[0]
        width=image_info[1]
        size=(height,width)
        print(size)
        fps=30
        fourcc=cv2.VideoWriter_fourcc(*"mp4v")
        video = cv2.VideoWriter(path_join(path_new,'join_photo.mp4'), cv2.VideoWriter_fourcc(*"mp4v"), fps, (width,height)) #创建视频流对象-格式一

        for i in range(len(os.listdir(path_new))):
            file_name = path_join(path_new,str(i) + '.jpg')
            print(file_name)
            image=cv2.imread(file_name)
            video.write(image)  # 向视频文件写入一帧--只有图像,没有声音

if __name__ == "__main__":
    copt_allfile()
    creade_video(rename_folder()) # 获取返回值

    # 写在最后的话,如果分辨率不同,那么在视频中,是无法加载出来的,就是根本看不到...

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值