python-2.7 - 如何处理 h264 格式的视频,修改每一帧并使用 openCV/ffmpeg 使用处理后的图像创建另一个 h264 格式的视频
问题描述
我想逐帧处理“h264”格式的视频。处理帧以添加某种噪声(例如椒盐噪声)并从处理后的图像(噪声图像)中重新创建“h264”格式的视频,其序列与原始“h264”视频相同。
我使用 openCV 进行了同样的尝试,但我没有得到任何可用的特定编解码器(cv2.VideoWriter 需要)来创建 h264 格式的视频。因此,我创建了嘈杂图像的 mp4 视频,然后使用 ffmpeg 将其从 mp4 转换为 h264 格式。但我想由于 h264 -> mp4 -> h264 转换,我从原始帧中丢失了太多信息。下面是我为此编写的代码。
import numpy as np
import os
from skimage.util import random_noise
def processVideo(videoPath, noiseType="", outVideoPath=""):
"""
Add the specified noise in the provided video.
videoPath: Video file path
noiseType: noise type which needs to be added in the video.
Supported noise types: gaussian, localvar, poisson, salt, pepper, s&p, speckle
Returns:
Noisy video path, in case of success
None, in case of failure
"""
if noiseType not in ['gaussian', 'localvar', 'poisson', 'salt', 'pepper', 's&p']:
print "noiseType is not specified."
return None
videoPath = os.path.abspath(videoPath)
print "The video path under process: {}".format(videoPath)
if outVideoPath:
outVideoPath = os.path.abspath(outVideoPath)
else:
outVideoPath = os.path.abspath(os.path.dirname(videoPath))
if os.path.exists(videoPath):
video = cv2.VideoCapture(videoPath)
if os.path.isdir(outVideoPath):
outVideoPath = os.path.join(outVideoPath, os.path.splitext(
os.path.basename(videoPath))[0] + "_Noisy" + ".mp4")
elif os.path.exists(outVideoPath):
print "The given location already contains the file named {}.\nPlease delete the same.".format(outVideoPath)
return None
elif os.path.exists(os.path.dirname(outVideoPath)):
outVideoPath = os.path.splitext(outVideoPath)[0] + ".mp4"
else:
print "The given location {} does not exists".format(os.path.dirname(outVideoPath))
return None
fourcc = cv2.VideoWriter_fourcc(*'MP4V')
frame_width = int(video.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(video.get(cv2.CAP_PROP_FRAME_HEIGHT))
video_fps = int(video.get(cv2.CAP_PROP_FPS))
totalFrames = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
print "Total Frames in video = ", totalFrames
out = cv2.VideoWriter(outVideoPath, fourcc, video_fps, (frame_width, frame_height))
while (video.isOpened()):
ret, frame = video.read()
if ret is True:
noise_img = random_noise(frame, mode=noiseType)
noise_img = np.array(255 * noise_img, dtype='uint8')
out.write(frame)
else:
video.release()
out.release()
break
return outVideoPath
else:
print "Provided Video Path: {} is not present in the specified location.".format(videoPath)
return None
def mp4Toh264VideoConv(mp4VideoPath, h264VideoPath=""):
mp4VideoPath = os.path.abspath(mp4VideoPath)
print "h264 video:", os.path.abspath(h264VideoPath)
if h264VideoPath:
h264VideoPath = os.path.abspath(h264VideoPath)
else:
h264VideoPath = os.path.abspath(os.path.dirname(mp4VideoPath))
if os.path.isdir(os.path.abspath(h264VideoPath)):
h264VideoPath = os.path.join(h264VideoPath, os.path.splitext(os.path.basename(mp4VideoPath))[0] + ".h264")
elif os.path.exists(h264VideoPath):
print "The given location already contains the file named {}.\nPlease delete the same.".format(h264VideoPath)
return None
elif os.path.exists(os.path.dirname(h264VideoPath)):
h264VideoPath = os.path.splitext(h264VideoPath)[0] + ".h264"
else:
print "The given location {} does not exists.".format(os.path.dirname(h264VideoPath))
return None
print "The h264 video path: ", h264VideoPath
os.system('ffmpeg -i ' + mp4VideoPath + ' -an -vcodec libx264 -crf 23 ' + h264VideoPath)
return h264VideoPath
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description='This script will add the specified noise in the given h264 video.')
parser.add_argument('-i', '--inputVideo', help='Input h264 formated Video Path', required=True)
parser.add_argument('-o', '--outputVideo', help='Output video path location', default="", required=False)
parser.add_argument('-n', '--noiseType', help='Type of noise to add in the video', default='', required=True)
args = vars(parser.parse_args())
inputVideo = os.path.expanduser(args['inputVideo'])
outputVideo = os.path.expanduser(args['outputVideo'])
noiseType = args['noiseType']
if os.path.splitext(inputVideo)[1].upper() != ".H264":
print os.path.splitext(inputVideo)[1].upper()
print "Noise Addition in {} formated video is not supported".format(os.path.splitext(inputVideo)[1])
exit(-1)
else:
noisymp4Video = processVideo(videoPath=inputVideo, noiseType=noiseType, outVideoPath=outputVideo)
if noisymp4Video:
mp4Toh264VideoConv = mp4Toh264VideoConv(mp4VideoPath=noisymp4Video, h264VideoPath=outputVideo)
exit(0)
else:
exit(-1)
我需要一些更好的方法来直接处理 h264 视频,在帧中进行一些修改并创建 h264 视频。如果 ffmpeg 和 openCV 组合可以做到这一点,我很好。我只需要一些更好的方法来防止由于 h264 -> mp4 -> h264 转换而造成的损失。
帮助将不胜感激。
解决方案
推荐阅读
- tsql - 验证电子邮件地址是否会被 sp_send_dbmail 接受?
- nuxt.js - 如何避免 nuxt 应用程序中的“客户端渲染的虚拟 DOM 树与服务器渲染的内容不匹配”警告?
- wcf - 在特定端口上托管 WCF 服务的问题
- excel - 有没有更好的方法来比较许多类似的字符串?
- html - 在单个 img 标签中显示多个 svg
- cookiecutter - 在 Google Colab 中安装 Cookiecutter
- java - Int 数组返回除一之外的所有零
- c++ - 检查2个指针是否为空
- amazon-s3 - 如何确保 S3 存储桶名称不与 Terraform 一起使用?
- variables - 使用 SQLCMD 在服务器之间传递标量变量的值