152 lines
4.7 KiB
Python
152 lines
4.7 KiB
Python
import threading
|
|
import time
|
|
|
|
import numpy as np
|
|
|
|
import pygame as pg
|
|
from moviepy.decorators import convert_masks_to_RGB, requires_duration
|
|
from moviepy.tools import cvsecs
|
|
|
|
pg.init()
|
|
pg.display.set_caption('MoviePy')
|
|
|
|
|
|
def imdisplay(imarray, screen=None):
|
|
"""Splashes the given image array on the given pygame screen """
|
|
a = pg.surfarray.make_surface(imarray.swapaxes(0, 1))
|
|
if screen is None:
|
|
screen = pg.display.set_mode(imarray.shape[:2][::-1])
|
|
screen.blit(a, (0, 0))
|
|
pg.display.flip()
|
|
|
|
|
|
@convert_masks_to_RGB
|
|
def show(clip, t=0, with_mask=True, interactive=False):
|
|
"""
|
|
Splashes the frame of clip corresponding to time ``t``.
|
|
|
|
Parameters
|
|
------------
|
|
|
|
t
|
|
Time in seconds of the frame to display.
|
|
|
|
with_mask
|
|
``False`` if the clip has a mask but you want to see the clip
|
|
without the mask.
|
|
|
|
"""
|
|
|
|
if isinstance(t, tuple):
|
|
t = cvsecs(*t)
|
|
|
|
if with_mask and (clip.mask is not None):
|
|
import moviepy.video.compositing.CompositeVideoClip as cvc
|
|
clip = cvc.CompositeVideoClip([clip.set_position((0, 0))])
|
|
img = clip.get_frame(t)
|
|
imdisplay(img)
|
|
|
|
if interactive:
|
|
result = []
|
|
while True:
|
|
for event in pg.event.get():
|
|
if event.type == pg.KEYDOWN:
|
|
if event.key == pg.K_ESCAPE:
|
|
print("Keyboard interrupt")
|
|
return result
|
|
elif event.type == pg.MOUSEBUTTONDOWN:
|
|
x, y = pg.mouse.get_pos()
|
|
rgb = img[y, x]
|
|
result.append({'position': (x, y), 'color': rgb})
|
|
print("position, color : ", "%s, %s" %
|
|
(str((x, y)), str(rgb)))
|
|
time.sleep(.03)
|
|
|
|
|
|
@requires_duration
|
|
@convert_masks_to_RGB
|
|
def preview(clip, fps=15, audio=True, audio_fps=22050, audio_buffersize=3000,
|
|
audio_nbytes=2, fullscreen=False):
|
|
"""
|
|
Displays the clip in a window, at the given frames per second
|
|
(of movie) rate. It will avoid that the clip be played faster
|
|
than normal, but it cannot avoid the clip to be played slower
|
|
than normal if the computations are complex. In this case, try
|
|
reducing the ``fps``.
|
|
|
|
Parameters
|
|
------------
|
|
|
|
fps
|
|
Number of frames per seconds in the displayed video.
|
|
|
|
audio
|
|
``True`` (default) if you want the clip's audio be played during
|
|
the preview.
|
|
|
|
audio_fps
|
|
The frames per second to use when generating the audio sound.
|
|
|
|
fullscreen
|
|
``True`` if you want the preview to be displayed fullscreen.
|
|
|
|
"""
|
|
if fullscreen:
|
|
flags = pg.FULLSCREEN
|
|
else:
|
|
flags = 0
|
|
|
|
# compute and splash the first image
|
|
screen = pg.display.set_mode(clip.size, flags)
|
|
|
|
audio = audio and (clip.audio is not None)
|
|
|
|
if audio:
|
|
# the sound will be played in parrallel. We are not
|
|
# parralellizing it on different CPUs because it seems that
|
|
# pygame and openCV already use several cpus it seems.
|
|
|
|
# two synchro-flags to tell whether audio and video are ready
|
|
videoFlag = threading.Event()
|
|
audioFlag = threading.Event()
|
|
# launch the thread
|
|
audiothread = threading.Thread(target=clip.audio.preview,
|
|
args=(audio_fps,
|
|
audio_buffersize,
|
|
audio_nbytes,
|
|
audioFlag, videoFlag))
|
|
audiothread.start()
|
|
|
|
img = clip.get_frame(0)
|
|
imdisplay(img, screen)
|
|
if audio: # synchronize with audio
|
|
videoFlag.set() # say to the audio: video is ready
|
|
audioFlag.wait() # wait for the audio to be ready
|
|
|
|
result = []
|
|
|
|
t0 = time.time()
|
|
for t in np.arange(1.0 / fps, clip.duration-.001, 1.0 / fps):
|
|
|
|
img = clip.get_frame(t)
|
|
|
|
for event in pg.event.get():
|
|
if event.type == pg.QUIT or \
|
|
(event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
|
|
if audio:
|
|
videoFlag.clear()
|
|
print("Interrupt")
|
|
return result
|
|
|
|
elif event.type == pg.MOUSEBUTTONDOWN:
|
|
x, y = pg.mouse.get_pos()
|
|
rgb = img[y, x]
|
|
result.append({'time': t, 'position': (x, y),
|
|
'color': rgb})
|
|
print("time, position, color : ", "%.03f, %s, %s" %
|
|
(t, str((x, y)), str(rgb)))
|
|
|
|
t1 = time.time()
|
|
time.sleep(max(0, t - (t1-t0)))
|
|
imdisplay(img, screen)
|