Как обработать видео в формате h264, изменить каждый кадр и создать другое видео в формате h264 с обработанными изображениями, используя openCV / ffmpeg - PullRequest
0 голосов
/ 04 ноября 2019

Я хочу обрабатывать отформатированное видео "h264" кадр за кадром. Обработайте кадр, чтобы добавить в него некоторый шум (например, шум соли и перца) и воссоздайте отформатированное видео «h264» из обработанных изображений (изображений с шумом) в той же последовательности, что и исходное видео «h264».

Я пытался сделать то же самое, используя openCV, но я не получаю какой-либо работающий определенный кодек (требуется cv2.VideoWriter) для создания видео в формате h264. Итак, я создал mp4-видео из зашумленных изображений, а затем преобразовал его из формата mp4 в h264 с помощью ffmpeg. Но я предполагаю, что теряю слишком много информации из исходного кадра из-за преобразования 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.

Заранее спасибо за помощь.

...