使用ffmpeg混合两个视频并增强视觉效果
由于远程容器的ffmpeg版本不包括mix功能,使用的是从网盘下的本地代码和本地的ffmpeg,仅上传了有改动的部分。
代码在code/notebook/_video.ipynb
,视频在code/video/outputxxx.mp4
由于播放视频的功能在容器中,所以在本地复制了一份
notebook_helpers.py
,稍微修改了代码确保正确导入。
给定的输入为两个完全看不出内容的视频,如下:
开始处理吧!
code/video/output.mp4
为直接使用ffmpeg混合两个输入得到的视频。可以看出视频内容为从8开始的倒计时,但不是很清楚。
- 首先观察到直接合成的视频对比度很低,先使用ffmpeg提高了对比度得到
code/video/output2.mp4
- 然后注意到视频中的噪点非常多,使用中值滤波和非局部平均去噪进行降噪,得到
code/video/output3.mp4
。- 该步骤非常耗时
- 如果跳过前一步增加对比度的操作直接降噪,会使得画面几乎完全看不清,再增加对比度也只能得到马赛克图像
也可以使用ffmpeg带的BM3D算法
- 视频经过滤波后,画面变得比较模糊,我希望通过锐化的方式让数字边缘看起来更清楚一些,得到
code/video/output4.mp4
- 锐化后噪点也看的更清楚了,使用中值滤波再处理一次,得到
code/video/output5.mp4
。由于最开始的噪声太强,如果不使用形状特征匹配,基本也就是这个效果了。
注意: opencv保存的mp4文件需要跟原视频一样使用avci编码才可以,然而需要额外下载openh264.dll文件放在目录中,直接使用的话会报错
Failed to load OpenH264 library: openh264-1.8.0-win64.dll
Please check environment and/or download library: https://github.com/cisco/openh264/releases
[libopenh264 @ 0000019f375b3cc0] Incorrect library version loaded
Could not open codec 'libopenh264': Unspecified error
为了展示每一步的效果,在jupyter里每次操作都是重新读写视频
In [1]: import subprocess from notebook_helpers import play_video import cv2 import numpy as np In [2]: # play video 1 play_video('../video/video_1.mp4') Out[2]: In [3]: # play video 2 play_video('../video/video_2.mp4') Out[3]: In [4]: # use ffmpeg to mix 2 videos subprocess.run(["ffmpeg", "-y","-i", "../video/video_1.mp4", "-i", "../video/video_2.mp4", "-filter_complex", "mix", "../video/output.mp4"]) Out[4]: CompletedProcess(args=['ffmpeg', '-y', '-i', '../video/video_1.mp4', '-i', '../video/video_2.mp4', '-filter_complex', 'mix', '../video/output.mp4'], returncode=0) In [5]: # play output video play_video('../video/output.mp4') Out[5]: In [6]: # change the contrast subprocess.run(["ffmpeg", "-y","-i", "../video/output.mp4", "-vf", "eq=contrast=9", "../video/output2.mp4"]) Out[6]: CompletedProcess(args=['ffmpeg', '-y', '-i', '../video/output.mp4', '-vf', 'eq=contrast=9', '../video/output2.mp4'], returncode=0) In [7]: # play output2 video play_video('../video/output2.mp4') Out[7]: In [8]: #中值滤波&非局部平均去噪 video_path = "../video/output2.mp4" cap = cv2.VideoCapture(video_path ) fps = cap.get(cv2.CAP_PROP_FPS) #获取视频的帧率 size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))#获取视频的大小 fourcc = cv2.VideoWriter_fourcc(*'avc1') #要保存的视频编码 #把处理过的视频保存下来 output_viedo = cv2.VideoWriter() #保存的视频地址 video_save_path = '../video/output3.mp4' output_viedo.open(video_save_path , fourcc, fps, size, True) while True: ret, image_np = cap.read() if not(ret): break image_np = cv2.medianBlur(image_np,7) #中值滤波 image_np = cv2.fastNlMeansDenoising(image_np, 15, 8, 25) #非局部平均去噪 output_viedo.write(image_np) #把帧写入到视频中 output_viedo.release()#释放 cap.release()#释放 In [9]: # play output3 video play_video('../video/output3.mp4') Out[9]: In [10]: #锐化 video_path = "../video/output3.mp4" cap = cv2.VideoCapture(video_path ) fps = cap.get(cv2.CAP_PROP_FPS) #获取视频的帧率 size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))#获取视频的大小 fourcc = cv2.VideoWriter_fourcc(*'avc1') #要保存的视频编码 #把处理过的视频保存下来 output_viedo = cv2.VideoWriter() #保存的视频地址 video_save_path = '../video/output4.mp4' output_viedo.open(video_save_path , fourcc, fps, size, True) while True: ret, image_np = cap.read() if not(ret): break kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]],dtype=np.float32) #锐化 image_np = cv2.filter2D(image_np, -1, kernel=kernel) output_viedo.write(image_np) #把帧写入到视频中 output_viedo.release()#释放 cap.release()#释放 In [11]: # play output4 video play_video('../video/output4.mp4') Out[11]: In [12]: #再一次中值滤波 video_path = "../video/output4.mp4" cap = cv2.VideoCapture(video_path ) fps = cap.get(cv2.CAP_PROP_FPS) #获取视频的帧率 size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))#获取视频的大小 fourcc = cv2.VideoWriter_fourcc(*'avc1') #要保存的视频编码 #把处理过的视频保存下来 output_viedo = cv2.VideoWriter() #保存的视频地址 video_save_path = '../video/output5.mp4' output_viedo.open(video_save_path , fourcc, fps, size, True) while True: ret, image_np = cap.read() if not(ret): break image_np = cv2.medianBlur(image_np,7) #中值滤波 output_viedo.write(image_np) #把帧写入到视频中 output_viedo.release()#释放 cap.release()#释放 In [13]: # play output5 video play_video('../video/output5.mp4') Out[13]:
notebook_helpers.py提供了在jupyter中播放视频的功能。
from IPython.display import HTML def play_video(path, width=320, height=240, format='mp4'): html = """ <video width="{width}" height="{height}" controls> <source src="{path}" type="video/{format}"> </video> """.format(path=path, width=width, height=height, format=format) return HTML(html)