github VisoMasterFusion/VisoMaster-Fusion v3.9.3
VisoMaster Fusion 3.9.3 Latest

5 hours ago

Highlights

  • Sortable & filterable target media list (new): the target videos/images panel can now be sorted by name, file date, file size, dimensions, total pixels or frame length in either direction, with file-type filters (images / videos / webcams) moved out of the popup menu into a togglable filter row, minimum width/height filters (synchronised slider + spin box), a search reset button, a loading progress bar, and rich tooltips showing name, type, date, size, path, dimensions and video length/frame rate/bitrate. Metadata is probed off the GUI thread (header-only for images, OpenCV properties for videos — no frame decoding), so sorting never blocks the UI.
  • VR180 face detectors (new): two dedicated detection models trained on VR180 content — Yolov11 VR180 (960×960) and Yolov12 VR180 (640×640) — selectable from Face Detect Model. These models output boxes only, so 5-point landmarks are synthesised from each bounding box via the canonical ArcFace template offsets and then run through the shared filtering/refinement pipeline.
  • Full K/V maps (new): a new Average K/V toggle lets you choose between averaging and full concatenation of the reference K/V maps used by the ReF-LDM denoiser. Embeddings now keep their raw, unbaked K/V tensor lists and merging is deferred to execution time, so switching the toggle takes effect immediately without re-extracting.
  • Border Seam Blend (new): a localized blur applied strictly to the outer mask border (morphological gradient based) to hide seams and hard cutoffs, independent of the existing whole-face Final Blend. The old "Final Blend" control is now labelled Final Blend (Whole Face) to make the distinction clear.
  • Worker architecture split (new): the monolithic frame_worker.py (~6,200 lines) was decomposed into a slim FrameWorker orchestrator plus PipelineProcessor (tensor math / inference / VRAM), StandardProcessor (flat video & images) and VRProcessor (VR180/360), and all model-function calls now route through a new FunctionWorker facade that owns the sub-processors centrally — worker threads no longer duplicate sub-processor caches.
  • Color correction fixes: the CDF-histogram and Reinhard transfer paths now exclude pure-black padding independently for source and target, which removes temporal flickering and the grey halos that could appear at warp edges.
  • First-launch execution-provider prompt: on a fresh install (no last_workspace.json), VisoMaster now asks which execution provider to use before anything loads, so you no longer trigger an unwanted TensorRT engine build on first start.
  • Legacy TensorRT engine support: engine caches are now written with an explicit per-model prefix, and existing legacy caches (generic TensorrtExecutionProvider_* naming) are detected and reused instead of being rebuilt.
  • Schema-aware save/load sanitization: workspaces, jobs, markers and per-face parameters are now validated against the live control/parameter schema on both save and load, instead of against a hardcoded list of removed keys. Obsolete keys are dropped and missing keys fall back to defaults.
  • Denoiser color controls simplified: the Denoiser Color Transfer Type selector and Color Strength slider were replaced by a single Color Correction toggle backed by masked Reinhard transfer at full strength.
  • Performance: broad micro-optimization pass across the denoiser, restorers, Recast and frame edits — direct tensor indexing instead of torch.gather, in-place tanh_/add_/mul_/clamp_ chains, CPU scalar math instead of torch.full allocations, non_blocking host↔device transfers, direct matmul instead of einsum, cached arange in head-pose decoding, and Kornia inverse affine warps.
  • Workspace conveniences: new Save Last Workspace / Reset Last Workspace and Quit / Quit without Saving menu entries, plus an Auto Save Last Workspace setting. Quit routes through close() so closeEvent still shuts the processing threads down.

Changelog by version

3.9.3

Target media sorting & filtering (app/ui/widgets/sortable_widgets.py, target_videos_list_actions.py) — PR #267:

  • SortableListWidget / SortableListWidgetItem hold sort keys as item data; targetVideosList is promoted to TargetVideosListWidget in MainWindow.ui.
  • Sort by name, file date, file size, dimensions, total pixels or frame length, ascending or descending.
  • File type filters (images / videos / webcams) moved from the popup menu into a togglable filter row; new minimum width/height filters with synchronised slider and spin box.
  • Search reset button, media-list loading progress bar and rich per-item tooltips.
  • Metadata probed via misc_helpers.probe_media_metadata() in the loader thread and delivered to the GUI thread on the thumbnail_ready signal — images read header-only via PIL, videos via OpenCV properties without decoding a frame.
  • The filter worker operates purely on a plain-value snapshot captured in the GUI thread; no QListWidgetItem or card widget crosses a thread boundary.
  • Sorting tie-breaks on file name so equal keys stay in a predictable order; items with no sort data (webcams) sink to the bottom instead of scrambling the order.
  • New icon glyph set for the filter/sort row.

Blend Adjustments:

  • Border Seam Blend (FinalBorderBlendEnableToggle) with Border Seam Blend Amount (1–50, default 5) — localized blur on the outer mask border only, implemented via a morphological gradient in the pipeline processor.
  • Final Blend renamed to Final Blend (Whole Face) with clarified help text; guarded against a zero sigma.

Denoiser:

  • Removed DenoiserColorTransferTypeSelection and DenoiserColorSlider; added a single Color Correction toggle (DenoiserColorCorrectionToggle, default ON) that applies masked Reinhard transfer in LAB space at locked 100% strength.

Execution providers & TensorRT:

  • First-launch Execution Provider prompt (CUDA / TensorRT / TensorRT-Engine / CPU) when no last_workspace.json exists, applied system-wide before models load — prevents accidental engine generation on a fresh install.
  • _check_tensorrt_cache replaced by _check_tensorrt_cache_state, which reports LEGACY (generic TensorrtExecutionProvider_* engine naming), EXPLICIT (custom per-model prefix) or None. Legacy caches bypass the explicit prefix so existing engines are reused instead of rebuilt.
  • Engine caches now written with an explicit trt_engine_cache_prefix per model to prevent collisions and make cleanup predictable.
  • _clean_tensorrt_cache handles both naming schemes, de-duplicates candidate prefixes, and sweeps auxiliary .profile / .cache / .timing files for every candidate prefix.

Save/load & job manager:

  • New sanitize_state_dictionary() validates a loaded control/parameter dict against the live reference dict (unknown keys dropped, missing keys defaulted) and sanitize_markers_dictionary() deep-sanitizes both control and per-face parameters inside markers.
  • Replaces sanitize_removed_settings_controls(), purge_removed_settings_controls(), scrub_removed_settings_from_markers() and the REMOVED_SETTINGS_CONTROL_KEYS blacklist — old workspaces and jobs no longer carry obsolete UI schema keys forward.
  • Applied consistently on workspace save/load, job save/load and batch job loading.
  • New Save Last Workspace / Reset Last Workspace and Quit / Quit without Saving menu entries; new Auto Save Last Workspace setting (writes last_workspace.json to the project root at the end of a recording).

Other:

  • Recast model components (PerformRecastAppearanceFeatureExtractor, …MotionExtractor, …WarpingModule, …SpadeGenerator) are now registered in MODELS_TOGGLE_MAP against FaceExpressionEnableBothToggle, so their VRAM is managed with the per-face toggle.
  • Removed autosorting of the embeddings list (reverts the 3.9.0 alphabetical sort — manual order is preserved again).

3.9.2

VR180 face detection models (face_detectors.py, models_data.py):

  • Yolov11 VR180 (YoloFace11nVR180, trained at 960×960) and Yolov12 VR180 (YoloFace12nVR180, trained at 640×640) added to Face Detect Model.
  • Both models output boxes only (output0: [1,5,N] = cx, cy, w, h, score) with no facial keypoints; a new _synthesize_kps_from_bboxes() helper derives 5-point landmarks from the box using canonical ArcFace 112×112 template offsets so the shared filtering/refinement path works unchanged.
  • Separate detect_yoloface11_vr180() / detect_yoloface12_vr180() paths with lazy engine build handling, post-rotation normalization and correct score-shape handling.
  • The VR perspective-grid detection pass now defaults to OFF (it can be re-enabled per project; the dedicated VR180 detectors cover most of what it was compensating for).

3.9.1

Structural changes — worker decomposition:

  • app/processors/workers/frame_worker.py reduced from ~6,300 lines to a focused FrameWorker orchestrator.
  • New frame_worker_pipeline.py (PipelineProcessor): heavy tensor operations, model inference and VRAM management inside the worker's CUDA stream, with LRU-bounded Gabor/convolution kernel caches and EMA-smoothed AutoColor reference statistics.
  • New frame_worker_standard.py (StandardProcessor): standard (flat) video and image processing.
  • New frame_worker_vr.py (VRProcessor): VR180/360 specific operations.
  • New function_worker.py (FunctionWorker): a thread-safe facade that centrally instantiates every sub-processor (detectors, landmarks, masks, restorers, swappers, enhancers, editors, re-aging, Recast, denoiser, frame edits), so worker threads no longer duplicate sub-processor caches and ModelsProcessor is decoupled from inference routing.
  • ModelsProcessor slimmed accordingly; every sub-processor now receives the models processor and the function worker, routing calls through the facade.
  • Follow-up commit completed the FunctionWorker migration across the pipeline, sequential detector, video processor and control actions.
  • Unit tests updated for the new module layout (test_frame_worker_vr.py, test_face_reaging.py, test_perform_recast.py).

3.9.0

Full K/V maps:

  • New Average K/V toggle (AverageKVToggle, default ON): averages the reference K/V maps, or concatenates the full maps when disabled.
  • Embedding cards now store the raw, unbaked K/V tensor list (kv_map_list) and merging is deferred to execution time, so the toggle takes effect without re-extraction; previously saved embeddings with a single baked kv_map still load (backward compatible).
  • handle_average_kv_toggle_change() synchronises the control dict before recalculating per-target-face K/V maps, fixing inverted merge behaviour, and clears the downstream combined VRAM maps.
  • KVExtractor.extract_kv() / get_kv_map_for_face() now accept either a PIL image or a tensor.

Color correction fixes (faceutil.py):

  • histogram_matching() builds its CDF from non-padding pixels only and restores pure-black padding after LUT application, preventing grey halos at warp edges.
  • histogram_matching_withmask() intersects the user mask with per-image validity masks so CDFs are computed strictly on real facial pixels (no zero-bin bias), with a safe early exit when nothing valid remains.
  • apply_reinhard_color_transfer() computes source and target statistics on independently validated pixel sets, with failsafes for entirely black sources — removes temporal flickering.

Optimizations:

  • Denoiser: direct tensor indexing instead of torch.gather, fused in-place normalization with non_blocking transfers, CPU scalar math for the DDIM/single-step alpha terms instead of torch.full allocations, and in-place tanh_().add_().mul_().clamp_() chains on the pre-allocated decode buffer.
  • Recast / restorers / frame edits: non_blocking matrix uploads, in-place math on freshly allocated tensors, direct inverse GPU affine warps via Kornia, matmul instead of einsum, a static arange cache in head-pose decoding, and removal of redundant del/try-except overhead.
  • KVExtractor padding path cleaned up.
  • Embeddings list gained alphabetical autosorting (removed again in 3.9.3).
  • Robustness: control lookups in calculate_assigned_input_embedding() use .get() with defaults, plus added type hints.

Contributors in this range

@Elricfae, @Glat0s, @mr-szgz — thanks to everyone who contributed code, fixes and reviews.


Upgrade notes

  • Portable launcher users: download the latest Start_Portable.bat attached to this release (or via the "latest" link in the README).
  • No manual migration steps required; the launcher's dependency update handles environment changes on next start.
  • The Yolov11 VR180 / Yolov12 VR180 detection models are downloaded on demand the first time you select them.
  • Existing TensorRT engine caches are detected and reused — engines built by earlier versions do not need to be rebuilt.
  • Workspaces and saved jobs from earlier versions load normally; the removed denoiser Color Transfer Type / Color Strength entries are sanitized out automatically and unknown keys now fall back to their defaults.
  • On a fresh install (no last_workspace.json), you will be asked to pick an execution provider on first launch. Choose CUDA or CPU if you want to avoid generating TensorRT engines during that first session.

Don't miss a new VisoMaster-Fusion release

NewReleases is sending notifications on new releases.