python将照片集导出成视频

shigen坚持更新文章的博客写手,记录成长,分享认知,留住感动。个人IP:shigen

背景

一个安静的下午,看着电脑里乱七八糟的照片,有大有小,宽高不一,突然想找个方式把他们统一起来,然后做成视频更好(其实我在上高中的时候就喜欢把照片做成视频,觉得意义很大)。要满足批量、自动化,肯定得动用代码了。于是首先我列举了下我希望的功能:

  1. 照片来源:制定的目录下所有的文件格式为照片的文件,按照照片的文件名进行排序
  2. 照片质量:按照目前的720P、1080P、甚至是2K、4K的画质来生成照片视频
  3. 照片横竖:可以自定义指定照片是横屏还是竖屏
  4. 照片时间:可以自定义每一张照片的放映时间
  5. 照片比例:这个也是最为重要的,对此我分成了如下几种case:
    1. 图片的宽度 < 视频宽度 * 50% or 图片的高度 < 视频高度 * 50%:舍弃掉
    2. 图片宽度 < 视频宽度 or 图片的高度 < 视频高度:居中等比放大,直到高度 = 视频高度 or 宽度 = 视频宽度=
    3. 其它尺寸,图片居中等比缩小,直到高度 = 视频高度 or 宽度 = 视频宽度

这种照片比例的放大居中,基本上是强迫症患者的福音了,严格的居中对齐。

实现

依托强大的python库,这里主要用到的工具库有:

  1. Pillow,源代码有简单、精炼的解释:**Pillow is the friendly PIL fork by Alex Clark and Contributors.PIL is the Python Imaging Library by Fredrik Lundh and Contributors.**机器学习、图像识别等场景用到的最多,这里主要使用它来调整图片的大小
  2. MoviePy, 是一个用于视频编辑的 Python 库。可以剪辑视频添加音频和字幕调整视频帧简单的特效等等。这里主要是根据照片序列生成视频。

介绍完主要的库之后,就是代码环节了,代码里注释较多,轻松入手,不做过多的解释:

# create viode from a dictionary which contains image or video files
import os
from PIL import Image
from moviepy.editor import ImageSequenceClip


def resize_and_crop(image, target_size):
    """将图片根据给定的大小进行缩放和裁剪

    1. 图片的宽度 < 视频宽度 * 50% or 图片的高度 < 视频高度 * 50%:舍弃掉
    2. 图片宽度 < 视频宽度 or 图片的高度 < 视频高度:居中等比放大,直到高度 = 视频高度 or 宽度 = 视频宽度
    3. 图片居中等比缩小,直到高度 = 视频高度 or 宽度 = 视频宽度

    Args:
        image (str): 原图片文件路径
        target_size (tuple): 视频大小(宽度, 高度)

    Returns:
        Image: 调整后的图片,可能为空
    """
    img = Image.open(image)
    video_width, video_height = target_size

    # 检查条件1:如果原图宽度或高度小于视频尺寸的50%,则返回None
    if img.width < video_width * 0.5 or img.height < video_height * 0.5:
        return None

    # 计算目标缩放比例
    scale_x = video_width / img.width
    scale_y = video_height / img.height

    # 根据需要的宽度和高度选择缩放比例
    if img.width < video_width or img.height < video_height:
        # 居中等比放大
        scale = max(scale_x, scale_y)
    else:
        # 居中等比缩小
        scale = min(scale_x, scale_y)

    # 放大或缩小图片
    new_size = (int(img.width * scale), int(img.height * scale))
    img = img.resize(new_size, Image.ANTIALIAS)

    # 计算裁剪框的位置
    left = (img.width - video_width) // 2
    top = (img.height - video_height) // 2
    right = left + video_width
    bottom = top + video_height

    # 裁剪并返回最终图片
    img = img.crop((left, top, right, bottom))
    return img


def create_video_from_images(folder_path,
                             out_put_file_name='output_video.mp4',
                             resolution='720p',
                             is_horizontal=True,
                             duration=3):
    """通过照片生成视频

    Args:
        folder_path (_type_): 文件夹路径
        out_put_file_name (str, optional): _description_. 视频输出路径 Defaults to 'output_video.mp4'.
        resolution (str, optional): _description_. 视频清晰度 Defaults to '720p'.
        is_horizontal (bool, optional): _description_. 是否是横屏 Defaults to True.
        duration (int, optional): _description_. 每张照片的放映时长 Defaults to 3.

    Raises:
        ValueError: 视频清晰度错误
    """
    resolution_mapping = {
        '720p': (1280, 720),
        '1080p': (1920, 1080),
        '2k': (2560, 1440),
        '4k': (3840, 2160),
    }

    if resolution not in resolution_mapping:
        raise ValueError(
            "Invalid resolution. Choose from '720p', '1080p', '2k', '4k'.")

    target_size = resolution_mapping[resolution]
    if not is_horizontal:
        target_size = (target_size[1], target_size[0])

    images = []

    # 读取文件夹下的文件并按照文件名排序
    for filename in sorted(os.listdir(folder_path)):
        if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp')):
            img = resize_and_crop(os.path.join(folder_path, filename),
                                  target_size)
            if img:
                images.append(img)

    # 照片的临时位置
    temp_files = []
    for i, img in enumerate(images):
        temp_file = f'temp_image_{i}.png'
        img.save(temp_file)
        temp_files.append(temp_file)

    # 创建视频
    clip = ImageSequenceClip(temp_files, fps=1 / duration)
    output_file = os.path.join(folder_path, out_put_file_name)
    clip.write_videofile(output_file, codec='libx264')

    # 清除临时文件
    for temp_file in temp_files:
        os.remove(temp_file)


if __name__ == '__main__':
    create_video_from_images(
        folder_path='/Users/xxxx/Downloads/xxx/imgs',
        is_horizontal=False,
        resolution='720p')

我们执行脚本,这里是控制台输出:

控制台输出

再来看看视频输出:

生成的视频

标准的720P H264编码,3&,21s的时长。有一张图是横屏的图,这里生成的视频中也根据高度放大进行了居中裁剪:

图片居中裁剪

整体的感觉还不错,特此写个博客分享出来。当然还有很多的优化点:

优化项

其实做的还是相当的粗糙,但是基本上还是省事儿了。考虑到的优化点有:

  1. 指定背景音乐并实现照片卡点
  2. 加上随机的特效切换

咳,目前想到的就这么多。作为工具,我觉得越简单越好,需要效率和我开发时间的权衡。

与shigen一起,每天不一样!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/895584.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

求最大公约数(c语言)

先看题&#x1f447; 我这里介绍的方法&#xff1a;辗转相除法&#xff1a; 最大公约数&#xff1a; 最大公约数是指同时能整除俩个或更多整数的最大正整数。 欧几里得算法就是求最大公约数的算法 求最大公约数涉及到一个数学原理的转换: 俩个数的最大公约数等于其中一个数和…

使用scss生成旋转圆圈

图片 html代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>…

Windows电脑桌面如何弄个好用的提醒备忘录?

在这个充满挑战的时代&#xff0c;每个人都渴望成为更好的自己。然而&#xff0c;随着生活节奏的加快&#xff0c;我们时常发现自己陷入了各种琐事之中&#xff0c;难以脱身。为了不让重要的事情被遗漏&#xff0c;一款好的提醒备忘录工具就显得尤为关键。那么&#xff0c;Wind…

白嫖正版xshell和XFTP

在哪里可以下载正版免费的xshell和XFTP&#xff0c;并且还能够获得官网免费持久更新 白嫖步骤 首先直接在浏览器搜索xshell官网 点进官网之后直接点击下载 接着点击免费授权页面 进入之后就可以免费下载了 下载安装完成后填写用户名和邮箱并提交&#xff0c;这里就以xshell为…

第6篇:无线与移动网络

目录 引言 6.1 无线网络的基础概念 6.2 无线局域网&#xff08;WLAN&#xff09;与IEEE 802.11 6.3 蓝牙与无线个域网&#xff08;WPAN&#xff09; 6.4 无线城域网&#xff08;WMAN&#xff09;与WiMax 6.5 ZigBee与智能家居 6.6 移动蜂窝网络&#xff08;3G/4G/5G&…

【str_replace替换导致的绕过】

双写绕过 随便输入一个 usernameadmin&passwords 没有回显测试注入点 usernameadmin or 11%23&passwords 回显hello admin测试列数 usernameadmin order by 3%23&passwords测试回显位 usernameadmi union select 1,2,3%23&passwords 没有显示数据&#xff0c;推…

如何保证数据库和缓存双写一致性?

1. 如何保证数据库和缓存双写一致性&#xff1f; 在高并发情况下&#xff0c;如果有大量的请求直接访问到数据库&#xff0c;由于数据库是将数据存储到磁盘当中的&#xff0c;每次访问时需要将数据以页的形式读取到内存当中&#xff0c;并且建立数据库连接、查询数据库中的数据…

个人健康系统|个人健康数据管理系统|基于小程序+java的个人健康数据管理系统设计与实现(源码+数据库+文档)

个人健康数据管理系统 目录 基于小程序java的个人健康数据管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师…

Python基础08

目录 1.Object-Oriented Programming 2.类 2.1类的定义 2.2实例化对象(构造函数) 2.3self 2.4cls 2.5实例变量(也叫属性) 2.6类属性 2.5初始化方法 2.7类方法 2.8静态方法 3.继承 3.1单继承 3.2多继承 3.3覆盖(Override) 1.Object-Oriented Programming 一切皆…

RabbitMQ service is already present - only updating service parameters

Windows下卸载RabbitMQ之后,然后重新注册RabbitMQ服务的时候,报错以下信息: D:\software\rabbitmq-server-4.0.2\rabbitmq_server-4.0.2\sbin>D:\software\rabbitmq-server-4.0.2\rabbitmq_server-4.0.2\sbin\rabbitmq-service.bat install RabbitMQ service is already …

动态规划-子数组系列——乘积最大子数组

1.题目解析 题目来源&#xff1a;152.乘积最大子数组——力扣 测试用例 2.算法原理 1.状态表示 由于题目给的数组中可以包含负数&#xff0c;因此求最大乘积有两种情况&#xff1a; a.负数乘以最小数得出最大乘积 b.整数乘以最大数得出最大乘积 所以需要两个表分别求出最大最…

MySQL 数据库迁移至达梦 DM8 常见问题

目录 如何让迁移到 DM 的表名大小写和 MySQL 保持一致 MySQL 迁移到 DM 报错&#xff1a;列[NAMES]长度超出定义 MySQL 迁移到 DM 报错&#xff1a;记录超长 索引错误 DM大小写敏感配置 表空间 新建用户 用户与模式的关系 省略模式名的优势 实际操作 如何让迁移到 DM…

【网络原理】——拥塞控制,延时/捎带应答,面向字节流,异常情况

阿华代码&#xff0c;不是逆风&#xff0c;就是我疯 你们的点赞收藏是我前进最大的动力&#xff01;&#xff01; 希望本文内容能够帮助到你&#xff01;&#xff01; 目录 一&#xff1a;拥塞控制&#xff08;重点&#xff09; 1&#xff1a;情境引入 2&#xff1a;解决方案…

【Docker】安装部署项目流程(Pycharm版)

安装部署步骤 1.准备项目 第一步要准备好你所需要部署的项目&#xff0c;确保在工作目录下所以程序.py文件正常调用并能正确运行 如上&#xff0c;main要在工作目录中能跑通&#xff0c;这里有一点需要注意 在IDE src不要标记为源代码根目录&#xff0c;观察一下是否能跑通代…

【计算机网络 - 基础问题】每日 3 题(五十)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

Java最全面试题->Java基础面试题->JavaSE面试题->面向对象面试题

面向对象 下边是我自己整理的面试题&#xff0c;基本已经很全面了&#xff0c;想要的可以私信我&#xff0c;我会不定期去更新思维导图 哪里不会点哪里 1.面向对象和面向过程的区别 面向对象&#xff1a; 优点&#xff1a;易维护&#xff0c;复用&#xff0c;扩展。面向对象…

解决DOTA-v2.0数据集上传结果至官网BUG: No space left on device

时间&#xff1a;2024.10.20 一、DOTA-v2.0数据集上传结果至官网BUG&#xff1a; No space left on device IOError at /evaluation1/ [Errno 28] No space left on device二、解决方法&#xff0c;法一 上传的结果文件太大了&#xff0c;把服务器磁盘占满了。 将结果中精度…

【算法】KMP字符串匹配算法

目录 一、暴力 二、KMP 2.1 思路 2.2 next数组 2.3 实现 2.4 例题 一个人能走的多远不在于他在顺境时能走的多快&#xff0c;而在于他在逆境时多久能找到曾经的自己。 …

elementui时间选择器time-picker返回值不对的问题

1. 问题 天杀的elementui的time-picker&#xff0c;导致我开发的系统出现了一次生产问题&#xff0c;原因竟然是因为组件库的bug&#xff01;直接上截图。 如图&#xff0c;正常情况下&#xff0c;选择时间后&#xff0c;想要得到的值理应是当天的时间&#xff0c;如图是当年…

zotero文献管理学习

1 zotero软件简介 zotero是一款开源的文献管理软件。如果你听说或使用过EndNote&#xff0c;那么可能会对“文献管理”有一定的概念。可以简单地这样理解&#xff1a;zotero一定程度上可以作为EndNote的平替。 EndNote需要注册付费&#xff0c;对于无专业科研机构隶属关系的企…