Opencv+Moviepy实现涂鸦视频和视频音轨分离合并操作。

代码细节:1、视频帧率取决不同opencv版本 2、从VideoCapture读出来的文件,没有了还能读!!所以最后一帧是None,用frame_s.pop()弹出3、注意内存各种占满所以对Moviepy的视频做.close()。对opencv()做.release()和cv2.destroyAllWindows()

4、代码设计,video ---> frame; frame ---> visual; video ---->audio; visual + audio ---> video.

from moviepy.editor import *
import xml.etree.ElementTree as ET
import os
import cv2
import glob
import shutil
import pdb

def draw_redNose_in_video(correspond_video, xml_root, probe):
    replaced = os.path.dirname(os.path.dirname(os.path.dirname(video_dst_multip)))
    print(correspond_video.replace(replaced, ''))
    
    index_s = []
    point_s = []
    # pdb.set_trace()
    src = glob.glob(correspond_video+'*')[0]
    # decoding xml
    for index, type_tag in enumerate(xml_root.findall(probe)):
        point = type_tag.find('point').text
        if index == len(xml_root.findall(probe)) - 1:
            frame_index = int(type_tag.find('frameIndex').text)  # The last frame may be out of the range.
        else:
            frame_index = int(type_tag.find('frameIndex').text) + 1

        index_s.append(frame_index)
        point_xy = point.split(',')
        point_s.append(point_xy)

    vidcap = cv2.VideoCapture(src)
    # Find OpenCV version
    (major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')

    if int(major_ver) < 3:
        fps = vidcap.get(cv2.cv.CV_CAP_PROP_FPS)
    else:
        fps = vidcap.get(cv2.CAP_PROP_FPS)

    # video --> frames
    frame_s = []

    if vidcap.isOpened():
        success = True
        while success:
            success, image = vidcap.read()
            if cv2.waitKey(10) == 27:
                break
            frame_s.append(image)
        # The last is None rather than a Image, so we drop it.
        frame_s.pop()
    else:
        print('read error')

    _, img_w, _ = frame_s[0].shape

    # frame --> visual
    if len(index_s) >= 2:

        min_index = index_s[0]
        index_stride = index_s[1] - index_s[0]
        max_index = min( index_s[-1] + index_stride, len(frame_s))
        index_s.append(max_index)

        # ## either:1/2:
        # head_index = index_s.pop(0)
        # tail_index = index_s.pop(0)
        #
        # x_y = point_s.pop(0)
        # img_array = []
        #
        # for id, item in enumerate(frame_s):
        #     rgb_item = cv2.cvtColor(item, cv2.COLOR_BGR2RGB)  # BGR[...,::-1] --> RGB
        #     if min_index <= id < max_index:
        #         if id >= tail_index:
        #             head_index = tail_index
        #             tail_index = index_s.pop(0)
        #             x_y = point_s.pop(0)
        #
        #         if head_index <= id < tail_index:
        #
        #             x_y = tuple([int(e) for e in x_y]) # list(x_y) --> tuple(x_y)
        #             cv2.circle(rgb_item, x_y, int(img_w/300.), (255, 0, 0), int(img_w/300.))
        #
        #     img_array.append(rgb_item)

        ## either:2/2:
        first_head = index_s[0]
        first_tail = index_s[1]

        last_head = index_s[-2]
        last_tail = index_s[-1]

        img_array = []
        for id, item in enumerate(frame_s):
            rgb_item = cv2.cvtColor(item, cv2.COLOR_BGR2RGB)  # BGR[...,::-1] --> RGB
            if first_head <= id < first_tail: # or last_head <= id < last_tail:

                if id < first_tail:
                    x_y = point_s[0]
                else:
                    x_y = point_s[-1]
                x_y = tuple([int(e) for e in x_y]) # list(x_y) --> tuple(x_y)
                cv2.circle(rgb_item, x_y, int(img_w/300.), (255, 0, 0), int(img_w/300.))

            img_array.append(rgb_item)

        # pdb.set_trace()
        drawed_video = ImageSequenceClip(img_array, fps=fps)
        # visual + audio --> video
        videoclip = VideoFileClip(src)
        videoclip2 = drawed_video.set_audio(videoclip.audio)

        # Write Video
        dst = src.replace(video_dir, video_dst_multip)
        parent_dst = os.path.dirname(dst)
        if not os.path.exists(parent_dst):
            os.makedirs(parent_dst)

        videoclip2.write_videofile(dst)

        # close all
        videoclip.close()
        videoclip2.close()
        drawed_video.close()

        del videoclip.make_frame
        del videoclip2.make_frame
        del drawed_video.make_frame

        del videoclip
        del videoclip2
        del drawed_video

        cv2.destroyAllWindows()
        vidcap.release()

def copy_video(correspond_video):
    replaced = os.path.dirname(os.path.dirname(video_dst_multip))
    print(correspond_video.replace(replaced, ''))
    src = glob.glob(correspond_video+'*')[0]
    dst = src.replace(video_dir, video_dst_single)
    parentDir_dst = os.path.dirname(dst)

    if not os.path.exists(parentDir_dst):
        os.makedirs(parentDir_dst)
    shutil.copy(src, dst)

def main(target_xml, video_dir):
    have = nothave = 0
    for index_id, (root, dirs, files) in enumerate(os.walk(target_xml)):
        # if index_id > 73:
        for xml in files:

            xml_dir = os.path.join(root,xml)
            xml_root = ET.parse(xml_dir).getroot()
            correspond_video = xml_dir.replace(target_xml, video_dir).replace('.xml', '')

            # To do or not to do
            src1 = glob.glob(correspond_video + '*')[0].replace(video_dir, video_dst_single)
            src2 = glob.glob(correspond_video + '*')[0].replace(video_dir, video_dst_multip)

            if not os.path.exists(src1) and not os.path.exists(src2):

                # some old_xml are not have these file
                head = 'videolabel'
                if xml_root.findall(head):
                    probe = os.path.join(head, 'points/facePoint')
                else:
                    probe = 'points/facePoint'

                # some are singlen's xml, some are rednose's xml
                if xml_root.findall(probe):
                    # rednose's xml
                    have += 1
                    draw_redNose_in_video(correspond_video, xml_root, probe)
                else:
                    nothave += 1
                    copy_video(correspond_video)

    # pdb.set_trace()
    print('have {}'.format(have))
    print('nothave {}'.format(nothave))

if __name__=='__main__':

    xmls_dir = '/home/debin/Desktop/schedule_management/Ideas/VideoDataset/sub_fromNSFC//Xmls_formNVL/pat1'
    video_dir = '/home/debin/Desktop/schedule_management/Ideas/VideoDataset/sub_fromNSFC/Videos_formNVL/pat1'

    video_dst_single = '/home/debin/Desktop/schedule_management/Ideas/VideoDataset/My_draw_Video/Single/pat1'
    video_dst_multip = '/home/debin/Desktop/schedule_management/Ideas/VideoDataset/My_draw_Video/Red_Node/pat1'
    main(xmls_dir, video_dir)

你可能感兴趣的:(general)