代码细节: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)