☞ ░ 老猿Python博文目录:https://blog.csdn.net/LaoYuanPython ░

一、引言

2021年4月8日武汉重启一周年,这是个值得庆祝的日子,作为一个武汉人和一个死宅程序员,老猿也想在这个日子留下点什么。想起武汉长江两岸的灯光秀,顿时有了主意,那就用程序实现一个武汉重启庆祝的灯光秀短视频吧,于是在4月7日晚开始构思和着手开发,4月8日晚终于顺利完成,并且通过使用OpenCV、OpenCV+Moviepy两种方式进行了实现。

本文介绍结合Python+OpenCV+Moviepy实现的思路和过程,Python+OpenCV实现的思路和过程将在另外的博文中单独介绍。

二、实现思路

2.1、视频内容设计

老猿是个没有艺术细胞的人,因此这个视频内容只能说仅能代表是个视频而已,对最终的内容表现大家就不需要过多评价。

在创作该视频前,对视频进行了简单规划,将创作视频分为片头、视频内容和片尾三部分:

  1. 片头:5秒时间,展现一幅黄鹤楼的照片,并带上“武汉重启一周年灯光秀”的标题
  2. 视频内容:全长35秒,每隔2秒随机展现一张武汉灯光秀景观图,并在视频中附上向上滚动的文字“热烈庆祝武汉重启一周年!”、“武汉万岁!中国万岁!”,并在视频的左下角和右下角用红绿蓝三色画三条向上晃动的线条表示彩色激光
  3. 片尾:25秒,每隔2秒随机展现武汉的一张风景照,并展现“制作:老猿Python”等制作信息。

2.2、开发设计

2.2.1、视频图片处理

视频中用到的图片都来源于互联网,为了确保视频输出,所有图片都调整到了统一大小。
在程序中通过全局变量将片头使用图像使用了全局变量进行保存,视频内容使用图像、片尾使用图像分别通过两个全局生成器进行访问,两个全局生成器能从列表中顺序取出图片,并在到达列表结尾时回到第一个元素。当然生成器访问的方法也可以不使用生成器而使用多个全局变量来实现。

2.2.2、灯光效果处理

在视频内容部分,左下角和右下角发射的彩色激光,采用在背景图片中根据时间动态绘制彩色线条,实现彩色激光晃动照射的效果,为了限制晃动范围,设定了激光终点的x值的最小值和最大值。激光终点的位置根据时间动态计算,并在到达x值的最小值或最大值时自动回扫。

2.2.3、帧图像的生成

为了符合Moviepy剪辑get_frame函数仅带一个时间参数t的要求,上面介绍的图像处理,全部集中在一个帧图像生成函数中处理,该函数仅带一个参数时间t。

帧图像生成函数判断时间来决定现在生成的内容是片头、内容还是片尾,然后据此来进行帧图像的生成。生成时,需要判断图像是否切换,因此需要记录上一次切换的时间和切换后的图像,确保未达到切换时间前用上次图像作为帧图像的背景,达到切换时间要求后切换新的图像作为后续帧图像生成的背景。为此在该函数中使用了两个全局变量来记录当前帧图像背景图片和上次切换时间。

2.2.4、输出到视频

为了将视频输出到文件,通过Moviepy构建剪辑,指定帧图像生成函数,并给视频附加音频,然后使用剪辑输出的方法将视频输出到指定文件,最终得到一个完整的视频。

三、具体实现

3.1、总流程

  1. 加载片头图像,构造视频内容、片尾需要使用图像访问的生成器;
  2. 构建帧图像生成函数,根据帧图像生成逻辑生成帧图像
  3. 加载并绑定音频音频、指定帧率、时长、帧图像生成函数构造视频剪辑对象;
  4. 将视频剪辑输出到文件。

3.2、定义两个图片获取生成器函数

两个图片获取生成器为构造视频内容、片尾提供背景图像;

def getLightShowImgFun():#定义灯光秀图片访问生成器函数lightShowImgList = [cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-一桥俯瞰.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-一桥激光.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-二七桥.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-二桥.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-晴川桥.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-月湖.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-汉口.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-汉口3.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-汉口江景.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-远光青山.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-隔江看汉口.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-青山.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-黄鹤楼.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀-龟山电视塔.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀_一桥.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀_一桥底部.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀_一桥远景.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀_桥.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀_桥上灯.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀_武汉江边.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀_远桥.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀江景.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀江滩.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀激光.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\灯光秀远观汉口.jpg'), (800, 600))]index = 0count = len(lightShowImgList)while True:index += 1if index>=count:index = 1yield lightShowImgList[index-1]def getWHImgFunc():#定义片尾图片访问生成器函数# 片尾背景图片whImgList = [cv2.resize(readImgFile(r'f:\pic\武汉\东湖1.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\东湖2.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\东湖樱园樱花.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\武大牌楼.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\武大牌楼远观.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\武大樱花2.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\武大樱园顶高拍照.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\武大樱园门洞.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\武大樱园入口.jpg'), (800, 600)),cv2.resize(readImgFile(r'f:\pic\武汉\武大老图书馆.jpg'), (800, 600))]index = 0count = len(whImgList)while True:index += 1if index>=count:index = 1yield whImgList[index-1]

3.3、全局变量初始化

全局变量主要是视频片头使用图片hhlImg、两个生成器,以及preImg,preTime用于记录上次切换视频图片的图片和切换时间。

#片头背景图片
hhlImg = cv2.resize(readImgFile(r'f:\pic\武汉\黄鹤楼.jpg'),(800,600))#灯光秀背景图片和片尾图片全局生成器初始化
getLightShowImg = getLightShowImgFun()
getWHImg = getWHImgFunc()#上次切换背景图片和切换时间全局变量初始化
preImg,preTime = None,0

3.4、实现给背景图像添加彩色激光照射效果

lightShowImg函数实现给背景图像指定点发射彩色激光的特效,激光发射点固定,由参数lightStartPos指定,终点随参数t在一定范围内变化,终点x坐标受参数minX, maxX控制,同一个发射源的三激光之间的间距受参数distance控制。

def lightShowImg(bg,minX, maxX,distance,lightStartPos,t):"""实现在背景图像上添加当前散发彩色激光的处理:param bg: 背景图像:param minX:灯光终点的最大x坐标:param maxX:灯光终点的最小x坐标:param distance: 不同灯光之间的间距:param lightStartPos: 灯光发射点:param t: 时间t:return: 添加了发射灯光的图像"""x =  (minX+int(t*200))%(maxX*2) #按时间t计算灯光终点的x坐标,该坐标可以超出背景图像范围img = np.array(bg)if x>maxX: #到达最大范围,需要回扫x = 2*maxX-xcolor1,color2,color3 = (255,0,0),(0,255,0),(0,0 ,255 ) #蓝、绿、红三色cv2.line(img, lightStartPos, (x, 0), color1, 4)cv2.line(img, lightStartPos, (x + distance, 0), color2, 4)cv2.line(img, lightStartPos, (x - distance, 0), color3, 4)return img

3.4、帧图片生成

makeframe函数实现帧图片生成,带一个参数t表示当前帧对应的剪辑时间,在函数内根据剪辑时间来判断是生成片头内容、灯光秀内容还是片尾内容生成t时刻对应帧图像返回。

def makeframe(t):"""makeframe函数实现帧图片生成,带一个参数t表示当前帧对应的剪辑时间,在函数内根据剪辑时间来判断是生成片头内容、灯光秀内容还是片尾内容生成t时刻对应帧图像返回:1. 对于片头,采用黄鹤楼照片作为背景,并在图片中央显示“武汉重启一周年灯光秀”;2. 对于视频内容,则每2秒从灯光秀图片队列中随机取一张图片作为当前背景图像,并调用lightShowImg增加左下角和右下角的彩色激光效果,同时动态向上滚动显示“热烈庆祝武汉重启一周年”、“武汉万岁!中国万岁!”等标语;3. 对于片尾,则每2秒从武汉风景图片队列中随机取一张图片作为当前背景图像,同时动态向上滚动显示制作信息。:param t: 生成帧对应剪辑的时间位置:return: 对应帧图像"""#生成t时刻的视频帧图像global preImg,preTimeprint(f"\rt={t:4.2f}", end='')if t<5:#5秒片头img = imgAddText(hhlImg,'武汉重启一周年灯光秀',64,(255,0,0),vRefPos='C')elif t<40:#5-40秒灯光秀minX, maxX = 200, 1200  # 灯光横向扫射范围lightStartPos1 = (0, 600)  # 灯光1的发射点坐标设置为左下角lightStartPos2 = (800, 600)  # 灯光2的发射点坐标设置为右下角if (t-preTime)>2 or preImg is None:img = next(getLightShowImg)preImg,preTime  = img,telse:img = preImgimg = lightShowImg(img, minX, maxX, 80,lightStartPos1, t)img = lightShowImg(img, minX-100, maxX+100,48, lightStartPos2, t)t = int((t-4)*40)%img.shape[0]img = imgAddText(img,'热烈庆祝武汉重启一周年!',48,(0,0,255),vRefPos=-80-t,)img = imgAddText(img, '武汉万岁!中国万岁!',48,(255,0,255),vRefPos=-t)else:#片尾if (t-preTime)>2 or preImg is None:img = next(getWHImg)preImg,preTime  = img,telse:img = preImgt = int((t - 39) * 20) % img.shape[0]img = imgAddText(img,"制作:老猿Python",36,(255,255,255),vRefPos=-120-t)img = imgAddText(img, "https://blog.csdn.net/LaoYuanPython",24,(255,255,255),vRefPos= -60-t)img = imgAddText(img, "2021年4月8日", 24, (255,255,255), vRefPos=-t)img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)return img

3.5、制作视频文件

函数buildVideo用于制作视频文件:

def buildVideo():#构建视频audio = AudioFileClip(r"F:\video\友谊之光.mp3").set_duration(65)clip = VideoClip(makeframe, False, 65).set_fps(24).set_audio(audio)clip.write_videofile(r"F:\video\lightShow.avi", codec='png', threads=8)

调用buildVideo函数即可完成视频制作。

3.6、视频效果

四、小结

本文完整介绍了用Python+OpenCV+Moviepy制作一个庆祝武汉重启一周年的武汉灯光秀短视频的实现思路、过程、关键函数等,有助于理解OpenCV的图像操作、Moviepy生成视频的实现。

更多相关moviepy知识的介绍请参考《https://blog.csdn.net/LaoYuanPython/article/details/108184832 Python音视频剪辑库MoviePy1.0.3中文教程导览及可执行工具下载》的导览式介绍。

写博不易,敬请支持:

如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

关于老猿的付费专栏

  1. 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
  2. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
  3. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录 》
  4. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。

前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

跟老猿学Python!

☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░

用Python+Moviepy+OpenCV制作灯光秀短视频相关推荐

  1. 用OpenCV-Python制作灯光秀短视频

    ☞ ░ 老猿Python博文目录:https://blog.csdn.net/LaoYuanPython ░ 用OpenCV-Python读取摄像头写入视频文件 一.引言 在<https://b ...

  2. 使用Python,OpenCV制作图像Mask——截取ROIs及构建透明的叠加层

    使用Python,OpenCV制作图像Mask--截取ROIs及构建透明的叠加层 1. 效果图 2. 源码 参考 这篇博客将介绍如何使用OpenCV制作Mask图像掩码.使用位运算和图像掩码允许我们只 ...

  3. 使用Python,OpenCV制作不同风格的素描图(正常,漫画,写实风格)

    使用Python,OpenCV制作不同风格的素描图(正常,漫画,写实风格) 这篇博客将介绍如何使用Python,OpenCV制作不同风格的素描图(正常风格,漫画风格,写实风格). 1. 效果图 原始图 ...

  4. 使用Python,OpenCV制作全透明的logo水印,对图像添加水印

    使用Python,OpenCV制作全透明的logo水印,对图像添加水印 1. 效果图 2. OpenCV自己制作一个logo(完全不透明的) 3. 制作水印图源码 4. 添加水印源码 5. 思考: 参 ...

  5. angular 多个片段拼接_教你怎么用手机制作和拼接短视频?

    多刚入门的短视频爱好者,看到抖音,快手,火山小视频上面的炫酷小视频很想 自己学会去怎么制作,然后又找不到相关的教程.在这里整理了几个适合新手在 手机上制作短视频 app 给大家! 用到的手机 app ...

  6. 会声会影x4素材_如何利用会声会影制作抖音短视频

    短视频的越发火爆,当我们看到抖音里面那些触动心弦的画面,那些震撼人心的画面,那些精彩纷繁的剪辑视频时候,是不是我们的内心也在呼唤,我该怎么制作抖音视频呢?下面小编就教大家如何利用会声会影制作抖音短视频 ...

  7. Android 制作一款短视频app软件可在线观看(视频实时更新)

    Android 制作一款短视频app软件可在线观看(视频实时更新) 第一步:完成界面的设计 界面布局采用LinearLayout,添加TextView控件显示标题,添加4个Button按钮可切换不同的 ...

  8. 主人给狗狗扔零食,小狗无奈吐槽,教你制作搞笑配音短视频

    主人给狗狗扔零食,小狗无奈吐槽,教你制作搞笑配音短视频 有时候,为自家的毛孩子拍摄了一段有趣的短视频之后,我们其实还可以尝试为它们配音,不仅可以让整个短视频更加的有趣,而且也更容易吸引粉丝,获得流量. ...

  9. 影视解说类视频怎么做,只需简单三步,教你制作影视解说短视频

    影视解说类视频怎么做,只需简单三步,教你制作影视解说短视频 影视解说类视频往往能够在很短的时间之内就将一部影视剧的大概剧情解说完毕,因此很多喜欢看剧的小伙伴们也跃跃欲试,想要尝试做做影视解说类短视频. ...

最新文章

  1. mutations vuex 调用_Vuex源码学习(六)action和mutation如何被调用的(前置准备篇)...
  2. Unity版本更新关注
  3. 双针模型:验证括号,特殊case处理
  4. Chapter7-1_Overview of NLP Tasks
  5. css3——新盒子定义box-sizing
  6. 高等数学中▽符号的作用
  7. 二、NPP/VIIRS夜间灯光数据校正之投影变换、裁剪、重采样
  8. 国密(1) - 私钥Key文件( PEM格式)编解码方法
  9. ThinkPad T61笔记本BIOS详细设置
  10. 程序员专属小情话,哎呦,不错哦!!!
  11. 推荐几个全网最全的程序员接私活地方法或完整攻略或常用平台以及接单的注意事项(以免被雇主坑),比如国内的程序员客栈、CODING 码市,国外的Upwork、Freelancer、Dribbble等。
  12. Vue3 - Element plus 实现 “带分页“ 表格组件,实现跨页进行 “分页勾选“ 的多选功能(解决分页表格组件 <el-table> 跨页后已前勾选的行自动消失问题)详细示例解决教程
  13. 【3分钟高效制作PPT】ChatGPT搭配闪击PPT生成PPT,你只需要输入一个标题
  14. 给每个物品一张“身份证”
  15. remap中的xmap,ymap详解
  16. 时间序列模型 (二):移动平均法
  17. C语言 day07 基础知识学习
  18. 初识Python之刨根问底
  19. 通往财富自由之路详细笔记(17)
  20. php使用fpm fcgi模式,为所有PHP模式安装Ioncube Loader(CLI,CGI,FCGI和FPM)在Debian Wheezy...

热门文章

  1. [T-ARA][TIAMO]
  2. 腾讯云从业者题库整理
  3. 【前端期末作业 基于jQuery鲜花销售管理系统】
  4. 2010年8月9日 流水账
  5. 超级玩家联想Z5s来了1398元起 顶配12GB划时代超旗舰联想Z5 Pro GT 855版惊艳亮相
  6. 顺丰快递代码表java,SF-CSIM-EXPRESS-SDK-V1.3 顺丰下单java后台demo代码 - 下载 - 搜珍网...
  7. java食堂外卖系统,java毕业设计_springboot框架的饭堂外卖系统
  8. 嵌入式系统设计 (考试题+答案)
  9. 人无远虑必有近忧,90后的我如何姑娘熬成婆
  10. burn suite启动_Microsoft计划(最终)启动Web Office Suite