Skip to content

Releases: fourMs/MGT-python

v1.6.0

27 Jun 17:03

Choose a tag to compare

Highlights

Added

  • Audio–movement analysis suite (compare a single performer's sound and motion):
    • tempo_similarity() — audio vs movement tempo (ratio, nearest harmonic, cross-correlation peak/lag)
    • phase_synchrony() — phase-locking value (PLV) + polar phase-difference plot
    • structure_comparison() — audio SSM vs movement SSM + difference map
    • body_audio_coupling() — per-marker correlation of speed with audio onset (body map + ranked bars)
    • dynamics_coupling() — audio loudness (RMS) vs quantity of motion
  • pose_segments() — circular (polar rose) motion plots and per-segment circular statistics (mean angle, R, circular std, range of motion, mean angular speed) + CSV
  • resample(fps=…, speed=…, skip=…) — retime an already-loaded video, returning a new MgVideo (duration-preserving fps change, speed factor with audio in sync, and/or frame decimation)
  • pose_waterfall(style=…) gained 'markers', 'skeleton', 'both' styles plus axes=False (clean render) and crop=True (trim to data); silhouette_waterfall() gained the same axes/crop options

Changed

  • pose(background='white') now also makes the trajectories image white (override with trajectory_background)

Fixed

  • Removed the white frame around the average-pose image
  • pose_waterfall(crop=True) no longer leaves a large empty margin

Documentation (with dance.avi illustrations) and the example notebook have been updated. See the CHANGELOG for full details.

v1.5.0

27 Jun 15:56

Choose a tag to compare

Highlights

Changed

  • Motiongram/videogram output filenames now use direction-of-movement suffixes — _mgh/_vgh (horizontal) and _mgv/_vgv (vertical) — replacing the axis-based _mgy/_vgy and _mgx/_vgx. Applied to motion(), motiongrams(), videograms(), motion_mp(), and the ssm() intermediates. All show(key=...) keys — 'horizontal'/'vertical', the new mgh/mgv/vgh/vgv aliases, and the legacy mgx/mgy/vgx/vgy — still resolve correctly.

Added

  • silhouette_waterfall() and pose_waterfall() accept axes=False to render without any axes, ticks, labels, panes, or title (a clean 3D image).

See the CHANGELOG for full details.

v1.4.9

27 Jun 15:33

Choose a tag to compare

Highlights

Added

  • pose_waterfall(style=...) — new 'markers', 'skeleton', and 'both' styles (drawing the pose at n_samples time slices) alongside the default 'trajectories'.
  • pose(trajectory_background=...)'black' (default), 'white', or 'transparent' background for the trajectories image (legacy transparent_trajectories still honoured).
  • Orientation aliases for show(key=...): mgh/vgh (horizontal) and mgv/vgv (vertical).

Changed

  • overwrite now defaults to True for all functions — outputs are overwritten in place instead of auto-incrementing the filename. Pass overwrite=False for the old behaviour.
  • MgVideo.beat_statistics() now defaults to source='motion' (analyses the movement rhythm), so it differs from video.audio.beat_statistics(). Use source='audio' for the audio track.
  • pose() container handling: convert defaults to None ("auto") — MediaPipe reads the source directly (no intermediate AVI), OpenPose still converts for frame-accurate decoding. The result video is written in the original container (mp4 in → mp4 out; no avi→mp4 round-trip).
  • Decluttered pose images: removed titles from the trajectories and waterfall images and the average-pose image, and removed the average-pose colorbar. Trajectories omit marker-name labels by default (trajectory_labels=True to re-enable).

Fixed

  • The show(key=...) orientation keys for motiongrams/videograms were swapped'horizontal' now selects the horizontal-movement gram and 'vertical' the vertical one, with correct titles (in both MgVideo.show and MgList.show).

See the CHANGELOG for full details.

v1.4.8

27 Jun 12:18

Choose a tag to compare

Highlights

Added

  • pose_waterfall() — a 3D spatio-temporal waterfall where each marker's trajectory flows through (x, time, y) space, a pose-based counterpart to silhouette_waterfall().
  • pose(marker_history=N) — motion trails for each marker over the last N frames.
  • pose(trajectory_labels=True) — opt back into per-marker name labels on the trajectories image.

Changed

  • pose() now defaults to the MediaPipe backend (fast on plain CPU, 33 landmarks with depth + visibility, no CUDA-enabled OpenCV build needed). OpenPose (body_25/coco/mpi) remains available for multi-person scenes.
  • pose(overlay=False, background='white') now draws a black skeleton + markers (print-friendly inverted look).
  • The marker-trajectories image no longer shows name labels by default.
  • tempogram() gains a colorbar (matching the chromagram) and shows the estimated tempo rounded to one decimal with "BPM" in the title; the dotted tempo line was removed.
  • videograms()/motiongrams() display keys are now 'horizontal'/'vertical'.

Fixed

  • motionhistory(): normalize defaults to False and is guarded so it no longer over-brightens ("blows up") static clips.
  • Documentation refreshed across the docs site, wiki, and READMEs; the stale releases.md page now tracks the changelog.

See the CHANGELOG for full details.

v1.4.7

27 Jun 10:43

Choose a tag to compare

What's new in 1.4.7

Fixed

  • GPU detection_utils.py never imported cv2, so CUDA was always reported absent. GPU acceleration now works on a CUDA-enabled OpenCV: pose(device='gpu') (OpenPose), flow.dense(use_gpu=True), flow.sparse(use_gpu=True).
  • GPU sparse optical flow path corrected (point shapes + calc() returns).
  • MgList.show(key='mgx'/'vgx'/…) on motiongrams/videograms no longer crashes — selects the right panel.
  • Audio methods inherited by MgVideo (e.g. video.spectrogram()) no longer fail on a missing cache attribute.
  • CI on macOS/Windows: skip .ogg tests without libtheora; force the Matplotlib Agg backend.

Added

  • pose(use_cache=True) — re-render a different style/overlay/background from cached keypoints without re-running inference.
  • pose(data_format='c3d') — export markers to a C3D motion-capture file (optional c3d dependency).
  • tempogram(onset_strength=False) — single-panel tempogram matching the chromagram size.
  • beat_statistics(source='motion') on MgVideo — timing statistics from movement onsets.

Changed

  • Average-pose labels: numbers only (normalised QoM 0–1 | dominant frequency), stronger de-overlap.
  • motiontempo(): QoM normalised 0–1, renamed "Motion spectrum", with average QoM and beat-frequency lines + numbers.

v1.4.6

27 Jun 09:27

Choose a tag to compare

What's new in 1.4.6

Added

  • Space-time person visualisations: stroboscope() (chronophotography), silhouette_waterfall(), motionhistory() (Motion History Image), and spacetime_volume() (3D x,y,t silhouette point cloud). Silhouettes use MediaPipe selfie segmentation when available, falling back to background subtraction (method='auto'|'mediapipe'|'bgsub').
  • ssm(features='motiongrams', combine=True) — a single self-similarity matrix combining horizontal + vertical motion in one display.
  • pose() style now also applies to the average-pose image.

Changed

  • pose(): no-CUDA fallback uses the MediaPipe CPU (XNNPACK) delegate (reliable) instead of the fragile OpenGL-ES GPU delegate; new quiet=True suppresses MediaPipe's native C++/GL logs.

Fixed

  • Orientation: portrait/phone videos with a rotation flag are normalised at load (rotation baked into pixels, flag removed), so cv2-based processes no longer come out rotated 90°.

v1.4.5

26 Jun 21:15

Choose a tag to compare

What's new in 1.4.5

Added

  • Pose overhaulpose() now also exports an average-pose image (markers coloured/labelled by average quantity of motion in px/frame + dominant movement frequency in Hz, plus a per-marker stats CSV) and an all-trajectories image; labels are laid out to avoid overlap. New rendering controls: style (both/markers/skeleton), overlay (on video or plain background), background (black/white), and transparent_trajectories (transparent PNG for overlaying). MediaPipe backend is GPU-capable on the standard pip OpenCV.
  • convert=False on pose(), flow.dense()/flow.sparse(), directograms(), impacts(), motion_mp(), history_cv2() to skip AVI conversion and read mp4 directly.

Changed

  • Display via show() — analysis results (MgImage/MgFigure) no longer auto-render as a notebook cell's last expression; call .show(). HTML available via to_html(). info('frame') now returns an MgImage.
  • blur_faces() writes MP4/libx264 instead of MJPEG-AVI.

Performance

  • MgAudio caches decoded audio (multiple audio analyses decode the file once).
  • ffprobe() results cached per file (path+mtime+size) — metadata helpers share one subprocess call.

Fixed

  • All "invalid escape sequence" SyntaxWarnings on import.
  • Documented MgVideo.length = frame count vs MgAudio.length = seconds.
  • Removed 30 unused imports.

v1.4.4

26 Jun 10:53

Choose a tag to compare

What's new in 1.4.4

Added

  • MgVideo.eulerian() — Eulerian Video Magnification (Wu et al., SIGGRAPH 2012) to reveal subtle changes. mode='color' amplifies subtle colour changes (pulse/breathing); mode='motion' amplifies subtle motion. Reads/writes via the FFmpeg pipe (any format) and is memory-conscious (two-pass color / streaming-IIR motion), addressing the format & memory limits of existing PyEVM ports. Closes #212.
  • MgVideo.sonomotiongram() — sonifies the motiongram by treating it as a magnitude spectrogram and resynthesising audio via inverse STFT (Griffin–Lim). Returns an MgAudio. Closes #171.
  • MgVideo.motionvectors() — visualises the motion vectors carried by inter-frame codecs (MPEG/H.264/H.265) via FFmpeg's codecview. Closes #254.

Fixed

  • EVM/sonomotiongram timing: MgVideo.length is a frame count (not seconds), so audio duration is computed as length/fps and progress is tracked in frames.

v1.4.3

26 Jun 10:11

Choose a tag to compare

What's new in 1.4.3

Added

  • MgVideo.heatmap() — motion heatmap showing which parts of the video change the most (optionally overlaid on the average frame).
  • MgVideo.motiontempo() — estimates dominant movement tempo (Hz + BPM) from the quantity of motion (addresses #158).
  • descriptors(save_data=True) — save per-frame audio descriptors to csv/tsv/txt (closes #124).
  • MediaPipe GPU posepose() uses MediaPipe's GPU delegate; when device='gpu' is requested but OpenCV lacks CUDA, it auto-switches to the MediaPipe backend so the GPU is actually used.
  • cuda_build_available() / cuda_unavailable_reason() helpers.

Changed

  • Display model: MgImage/MgFigure no longer auto-render as a cell's last expression — display happens only via show(). This removes the duplicate (small + large) outputs from the audio figure methods and makes average() display only when show() is called. HTML helper kept as to_html().
  • GPU-fallback messages now explain the real cause (pip OpenCV is built without CUDA) rather than implying a missing GPU.

Fixed

  • spectrogram()/descriptors() time axis pinned to the actual data extent — no more trailing whitespace or mislabeled timeline when the container is longer than the decoded audio.

V1.4.2

26 Jun 09:29

Choose a tag to compare

Fixed

  • Critical: repaired a thresholdold corruption (from a botched threshthreshold
    replace) that broke the FFmpeg threshold filter, leaving motion(), motiongrams()
    and related functions producing no frames and crashing. Motion analysis works again.
  • skip with large values no longer crashes: atempo filters are chained for ratios
    above FFmpeg's per-filter limit of 100, and colons are stripped from output filenames.
  • Restored consistent behaviour of the threshold/filtertype options in motiongrams().

Added

  • info(type='summary') now reports video codec/profile, pixel format, color space,
    and audio codec/sample-rate/bit-rate alongside resolution, frames, fps, and duration.
  • audio.mfcc(), audio.tempo() (beat tracking with tempo, beat times, inter-beat
    intervals and beat regularity), and audio.beat_statistics() (circular timing analysis).
  • musicalgestures/_analysis.py: general signal/statistics utilities (smooth,
    bandpass, dominant_frequency, circular_stats, rayleigh_test, synchrony),
    exported at package level.