【小工具系列】Python + OpenCV 图片序列转换成视频
图片序列转换成视频
最近一直在找一个工具,能够将一堆图片转化成视频。网上找了一些小软件,还有 win10 的照片自带的视频制作功能,都不是很满意。
又不想下载那些专业的视频剪辑软件大材小用。
然后找到了ffmpeg这个非常出名非常常用的多媒体编解码库,看了下文档试着用了下,它确实可以完成上述功能,但是命令行对输入图片的命名有规定(文件名必须开头相同、且包含连续编号),并且windows下的编译版不支持Pattern type 'glob'。
先尝试了用python写了批量重命名然后调用ffmpeg的命令,然后发现还需要相同的分辨率才行。。。
最后决定参照网上的其他使用OpenCV(OpenCV在视频处理功能底层也是用的ffmpeg)的博客自己写一个。
这里先把完整代码和使用说明贴出来:
import os, sys
import cv2
import numpy as np
import argparse
imgs_path = 'C:\\'
target_size = (1280, 720)
target_fps = 1.0
# 输出文件名
target_video = 'out.mp4'
# 是否保存 resize 的中间图像
saveResizeFlag = False
img_types = ('.bmp', '.dib', '.png', '.jpg', '.jpeg', '.pbm', '.pgm', '.ppm', '.tif', '.tiff')
# 不存在则创建目录
def mkdir(path):
if not os.path.exists(path):
os.mkdir(path)
# 将图片等比例缩放,不足则填充黑边
def resizeAndPadding(img):
size = img.shape
h, w = size[0], size[1]
target_h, target_w = target_size[1], target_size[0]
# 确定缩放的尺寸
scale_h, scale_w= float(h / target_h), float(w / target_w)
scale = max(scale_h, scale_w)
new_w, new_h = int(w / scale), int(h / scale)
# 缩放后其中一条边和目标尺寸一致
resize_img = cv2.resize(img, (new_w, new_h))
# 图像上、下、左、右边界分别需要扩充的像素数目
top = int((target_h - new_h) / 2)
bottom = target_h - new_h - top
left = int((target_w - new_w) / 2)
right = target_w - new_w - left
# 填充至 target_w * target_h
pad_img = cv2.copyMakeBorder(resize_img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=[0,0,0])
return pad_img
def imgs2video():
output_path = imgs_path + 'out\\'
mkdir(output_path)
target = output_path + target_video
fourcc = cv2.VideoWriter_fourcc(*"mp4v")
vw = cv2.VideoWriter(target, fourcc, target_fps, target_size)
images = os.listdir(imgs_path)
count = 0
for image in images:
if not (image.lower().endswith(img_types)):
continue
try:
print(image)
# cv2.waitKey(100)
# frame = cv2.imread(imgs_path + image)
# imread 不能读中文路径,unicode也不行
frame = cv2.imdecode(np.fromfile(imgs_path + image, dtype=np.uint8), cv2.IMREAD_COLOR) #, cv2.IMREAD_UNCHANGED
pad_frame = resizeAndPadding(frame)
# print(pad_frame.shape)
if saveResizeFlag:
# 保存缩放填充后的图片
resize_path = imgs_path + 'resize\\'
mkdir(resize_path)
resize_name = resize_path + 'resize_' + image
# cv2.imwrite(resize_name, pad_frame)
# imwrite 不能读中文路径,unicode也不行
cv2.imencode(os.path.splitext(image)[-1], pad_frame)[1].tofile(resize_name)
# 写入视频
vw.write(pad_frame)
count += 1
except Exception as exc:
print(image, exc)
vw.release()
print('\r\nConvert Success! Total ' + str(count) + ' images be combined into the video at: ' + target + '\r\n')
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Function: convert images to video")
parser.add_argument('--input', '-i', required = True)
parser.add_argument('--output', '-o', default='out.mp4')
parser.add_argument('--fps', '-f', type=float, default = 1.0)
parser.add_argument('--resolution', '-r', type=int, nargs = 2, default = [1280, 720])
parser.add_argument('--save', '-s', action='store_true')
args = parser.parse_args()
if args.input:
if not os.path.isdir(args.input):
print("input is not a directory")
sys.exit(0)
imgs_path = args.input
if not imgs_path.endswith(('\\', '/')):
imgs_path += os.path.sep
print('input path: ' + imgs_path)
if args.output:
target_video = args.output
print('output file: ' + target_video)
if args.fps:
if not args.fps > 0:
print('fps should be greater than zero')
sys.exit(0)
target_fps = args.fps
print('output file fps: ' + str(target_fps))
if args.resolution:
if not args.resolution[0] > 0 and args.resolution[1] > 0:
print('resolution should be greater than zero')
sys.exit(0)
target_size = (args.resolution[0], args.resolution[1])
print('output file resolution: ' + str(target_size))
if args.save:
saveResizeFlag = True
imgs2video()
使用方法:
- 依赖
numpy和cv2:(当然首先得有 Python 环境)
pip install numpy
pip install opencv-python
- 下载本代码到本地;
- 在命令行运行本代码,并指定参数:
python imgs2video.py -i D:\images\
python imgs2video.py -i D:\images\ -o test.mp4 -f 0.5 -r 1920 1080 -s
- 参数介绍:
--input, -i: 输入图片的路径,必须参数;
--output, -o: 输出视频的名字,默认 out.mp4;
--fps, -f: 指定的帧率,类型浮点数,默认 1.0;
--resolution, -r: 指定视频的分辨率,类型两个整数,默认 1280 720;
--save, -s: 是否保存图片转化分辨率之后的中间结果,默认不保存。
说明
代码看起来有点长,其实核心功能在函数imgs2video中:创建一个cv2.VideoWriter用于写视频文件,cv2.imdecode读图片,然后缩放,然后写入视频。可选项:cv2.imencode将缩放后的图片保存下来。之所以不用cv2.imread和cv2.imwrite是因为这俩没办法处理中文路径
函数resizeAndPadding用于将图片等比例缩放至指定分辨率,并往周围填充黑边(想用其他颜色在代码里改一改value=[0,0,0]这里的 RGB 值就行了)。这个函数本身也可以实现某些需求了。
main里面主要是处理命令行的一些参数,指定输入文件、输出文件、分辨率、帧率等
输出文件类型目前用的mp4,可以指定其他类型试试。我自己试过avi但是在帧率低的时候表现不太正常。指定其他类型可能需要把fourcc = cv2.VideoWriter_fourcc(*"mp4v")这里的"mp4v"改成其他的,具体怎么改可以搜一下,这里就不一一列举了。(这里有一个奇妙 BUG,写"MP4V"反正会报出错误,虽然能正常生成视频。在StackOverFlow上看见有人说改成"mp4v"就正常了,试了下还真的是。。。。)
其他功能的说明在上文使用方法里都有写。
后记
折腾了一天写了个用处不大的小工具。如果此代码对你有帮助可以在该github仓库点个Star。
【小工具系列】Python + OpenCV 图片序列转换成视频的更多相关文章
- Python OpenCV图片转视频 工具贴(三)
Python OpenCV图片转视频 粘贴即用,注意使用时最好把自己的文件按照数字顺序命名.按照引导输入操作. # 一键傻瓜式引导图片串成视频 # 注意使用前最好把文件命名为数字顺序格式 import ...
- 分别用Excel和python进行日期格式转换成时间戳格式
最近在处理一份驾驶行为方面的数据,其中要用到时间戳,因此就在此与大家一同分享学习一下. 1.什么是时间戳? 时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01 ...
- 把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend
//把一个序列转换成严格递增序列的最小花费 CF E - Sonya and Problem Wihtout a Legend //dp[i][j]:把第i个数转成第j小的数,最小花费 //此题与po ...
- 把一个序列转换成非严格递增序列的最小花费 POJ 3666
//把一个序列转换成非严格递增序列的最小花费 POJ 3666 //dp[i][j]:把第i个数转成第j小的数,最小花费 #include <iostream> #include < ...
- 用Python将word文件转换成html(转)
用Python将word文件转换成html 序 最近公司一个客户大大购买了一堆医疗健康方面的科普文章,希望能放到我们正在开发的健康档案管理软件上.客户大大说,要智能推送!要掌握节奏!要深度学习!要 ...
- js 将图片文件转换成base64
1.情景展示 在JavaScript中,如何使用图片文件转换成base64? 2.解决方案 /** * 网络图像文件转Base64 * @param img dom对象 */ function g ...
- js如何将选中图片文件转换成Base64字符串?
如何将input type="file"选中的文件转换成Base64的字符串呢? 1.首先了解一下为什么要把图片文件转换成Base64的字符串 在常规的web开发过程中,大部分上传 ...
- matlab下将图片序列转化为视频文件 && 将为视频文件转化图片序列
将图片序列转化为视频文件 程序如下: framesPath = 'E:\img\';%图像序列所在路径,同时要保证图像大小相同 videoName = 'Bolt.avi';%表示将要创建的视频文件的 ...
- python入门:UTF-8转换成GBK编码
#!/usr/bin/env python # -*- coding:utf-8 -*- #UTF-8转换成GBK编码 #temp(临时雇员,译音:泰坡) #decode(编码,译音:迪口德) #en ...
随机推荐
- 为什么选择ASP.NET Core
什么是.NET 有一次小飞去面试,面试官上来就问了一个宏观的问题:"你觉得什么是.NET"?小飞的脑子嗡嗡的,支吾了半天,才吐了一些碎片化的词语:"跨平台.开源.微软-& ...
- Python小白的数学建模课-09 微分方程模型
小白往往听到微分方程就觉得害怕,其实数学建模中的微分方程模型不仅没那么复杂,而且很容易写出高水平的数模论文. 本文介绍微分方程模型的建模与求解,通过常微分方程.常微分方程组.高阶常微分方程 3个案例手 ...
- 4.2tensorflow多层感知器MLP识别手写数字最易懂实例代码
自己开发了一个股票智能分析软件,功能很强大,需要的点击下面的链接获取: https://www.cnblogs.com/bclshuai/p/11380657.html 1.1 多层感知器MLP(m ...
- CosId 通用、灵活、高性能的分布式 ID 生成器
CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...
- 环境安装——MySQL安装
@ 目录 一文教会你安装与卸载MySQL 1. 官网下载 2. 文件下载 3. 卸载步骤 4. 安装步骤 5. MySQL配置 6. 安装出现的问题 6.1 如果出现了最后一步卡死的状态的话,不要慌: ...
- 《面试补习》- Java集合知识梳理
一.ArrayList ArrayList 底层数据结构为 动态数组 ,所以我们可以将之称为数组队列. ArrayList 的依赖关系: public class ArrayList<E> ...
- .net core 支付宝,微信支付 三
支付回调: 获取HttpRequest的body内容,之前使用Request.Form有时候数据请求不到(可能是跟.net core 版本有关?) var s = HttpRequest.Body; ...
- Git&Gitlab开发流程与运维管理
Git&Gitlab开发流程与运维管理 作者 刘畅 时间 2020-10-31 实验系统版本centos7.5 主机名称 ip地址 配置 安装软件 controlnode 172.16.1.1 ...
- 如何使用「mkvtoolnix」和「GoldWave」仅保留视频中左、右声道的其中一个声道?
为什么要这样做? 我手上有一部电视剧的视频文件(.rmvb),每个视频文件都是"国/粤双语"的,与其他双语视频的两种语言的音频保存在两个音轨上不同,我这里的视频文件的双语是分别保存 ...
- SpringBoot Validation参数校验 详解自定义注解规则和分组校验
前言 Hibernate Validator 是 Bean Validation 的参考实现 .Hibernate Validator 提供了 JSR 303 规范中所有内置 constraint 的 ...