在《OpenCV-Python常用图像运算:加减乘除幂开方对数及位运算》介绍了OpenCV主要的图像运算,视频是由一帧帧图像构成,通过OpenCV和Moviepy的灵活运用,可以实现一些特殊的特效。本文将介绍通过OpenCV图像运算+Moviepy实现视频叠加透明效果。
本案例实现一个可以在视频上面叠加一个旋转视频或旋转图片的通用方法,支持两个内容大小不同的视频叠加。为了支持叠加对象为图片,需要将图片转换成视频,为了尽可能突出图片的表达内容,在将图片转视频前将图片的背景色转换为黑色。
相关程序包括如下函数:
上述函数中关键函数为get_frame、videoOverlyObjMask,这二个函数是视频旋转并叠加的主程序代码。相关程序代码如下:
def get_frame(level0Clip,level1Clip,t):
"""
功能:根据两个大小不同的剪辑生成结果剪辑的帧
:param level0Clip: 底层的剪辑,一般要求该剪辑的宽和高度不小于上层剪辑的宽和高,如果超过就只剪裁掉超出范围的边缘部分
:param level1Clip: 上层剪辑,要求该剪辑为黑色的部分不能覆盖底层剪辑的图像
:param t: 帧对应时刻
:return: 新剪辑对应t时刻的合成帧,其图像为上层剪辑非透明部分叠加底层剪辑未被上层非透明部分覆盖部分
"""
img1 = level0Clip.get_frame(t)
img2 = level1Clip.get_frame(t)
if img1.size!=img2.size:#如果两个剪辑大小不同
img2 = adjustImgAccordingToRefImg(img2, img1) #根据底层剪辑的帧大小调整上层剪辑的大小,确保最终两个剪辑大小一致
#取上层剪辑的非透明部分和底层剪辑未被覆盖部分
imgGray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) #将上层剪辑帧图像转成灰度图
retval, imgMask = cv2.threshold(imgGray, 1, 255, type=cv2.THRESH_BINARY) #将灰度图二值化作为掩膜
maskInv = cv2.bitwise_not(imgMask) #上层剪辑掩膜求反,用于获取底层剪辑需要显示内容
result = cv2.bitwise_and(img2, img2, mask=imgMask) + cv2.bitwise_and(img1, img1, mask=maskInv)
return result
def videoOverlyRotateObj(videoFName,objType='self',obj=None):
"""
剪辑自身叠加一个该剪辑旋转的层,旋转层黑色的部分不能遮挡下层的剪辑内容
:param videoFName: 剪辑来源视频文件
:param objType、obj:
self:剪辑自身叠加自身旋转内容,obj值忽略
img:图片文件或图片矩阵对象,obj值为图片文件名会图片对象
video:视频文件或剪辑,obj为视频文件名或剪辑对象
:return: 参数视频剪辑自叠加一个旋转层对象,旋转层由参数objType、obj决定,对象大小最好小于videoFName对应视频大小,否则会被裁减
"""
clip = VideoFileClip(videoFName, audio=True)
if objType=='self':
objClip = clip
elif objType=='img':
objClip = convertPicToVideo(obj, duration=clip.duration, createMask=False).set_fps(clip.fps)
elif objType=='video':
if isinstance(obj,str): objClip = VideoFileClip(obj, audio=False)
else: objClip = obj
maskclip = objClip.rotate(angleF,expand=True).fx(vfx.resize,clip.size)
make_frame = lambda t:get_frame(clip,maskclip,t)
newclip = VideoClip( make_frame=make_frame, duration=clip.duration).set_fps(clip.fps)
return newclip
if __name__=='__main__':
result1 = videoOverlyRotateObj(r"F:\video\WinBasedWorkHard_src.mp4",'img',r'F:\pic\Lotus.JPG')
result1.write_videofile(r"F:\video\WinBasedWorkHard_new.mp4", threads=8)
result2 = videoOverlyRotateObj(r"F:\video\WinBasedWorkHard_src.mp4")
result2.write_videofile(r"F:\video\WinBasedWorkHard_mask_self.mp4", threads=8)
result3 = videoOverlyRotateObj(r"F:\video\WinBasedWorkHard_src.mp4",'img',r'F:\pic\Lotus.JPG')
result3.write_videofile(r"F:\video\WinBasedWorkHard_mask_pic.mp4", threads=8)
result4 = videoOverlyRotateObj(r"F:\video\mydream.mp4", 'video',r"F:\video\WinBasedWorkHard_src.mp4")
result4.write_videofile(r"F:\video\WinBasedWorkHard_mask_video.mp4", threads=8)
为了与付费专栏的文章有所差别,其他次要函数在此就不提供代码了。本文对应的付费专栏文章为《使用OpenCV图像运算+Moviepy实现视频叠加案例》。
本文详细了使用OpenCV图像运算+Moviepy实现视频叠加后,最终结果剪辑中的上层剪辑和下层剪辑叠加后,上层剪辑背景色部分被下层剪辑内容所呈现替代的方案。通过该实现案例的介绍,可以理解OpenCV图像运算在图像处理中的作用,并在多个剪辑制作特效中使用该方法制作视频特效。
如果觉得本文可以给您带来帮助,请大家帮忙点个赞、加个收藏,谢谢!
更多OpenCV-Python的介绍请参考专栏《OpenCV-Python图形图像处理 》
专栏网址:https://blog.csdn.net/laoyuanpython/category_9979286.html
更多moviepy的介绍请参考《PyQt+moviepy音视频剪辑实战文章目录》或《moviepy音视频开发专栏》。这2个专栏内容的导读请参考《Python音视频剪辑库MoviePy1.0.3中文教程导览及可执行工具下载》。
本文对应的付费专栏文章为《使用OpenCV图像运算+Moviepy实现视频叠加案例》。
老猿的付费专栏《使用PyQt开发图形界面Python应用 》(https://blog.csdn.net/laoyuanpython/category_9607725.html)专门介绍基于Python的PyQt图形界面开发基础教程,付费专栏《moviepy音视频开发专栏》 (https://blog.csdn.net/laoyuanpython/category_10232926.html)详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,两个专栏都适合有一定Python基础但无相关知识的小白读者学习。
付费专栏文章目录:《moviepy音视频开发专栏文章目录》(https://blog.csdn.net/LaoYuanPython/article/details/107574583)、《使用PyQt开发图形界面Python应用专栏目录 》(https://blog.csdn.net/LaoYuanPython/article/details/107580932)。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《专栏:Python基础教程目录》(https://blog.csdn.net/laoyuanpython/category_9831699.html)从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。