使用ffmpeg混合两个视频并用opencv增强视觉效果

使用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)
原文地址:https://www.cnblogs.com/smileglaze/p/13943236.html