Add BiM-VFI as interpolation method for direct transitions
Integrate KAIST VICLab's BiM-VFI (CVPR 2025) as a third option alongside RIFE and FILM for AI frame interpolation between sequences. - Add BIM_VFI enum value to DirectInterpolationMethod - Create core/bim_vfi_worker.py subprocess worker following FILM pattern - Add BimVfiEnv class managing repo clone, deps install, and checkpoint download (via gdown from Google Drive) - Add batch and single-frame dispatch in TransitionGenerator - Add bim_vfi_blend() to ImageBlender with FILM fallback - Update DirectTransitionDialog UI with BiM-VFI option and setup flow BiM-VFI setup auto-clones the repo, installs deps (cupy, basicsr-fixed, etc.) into the shared PyTorch venv, and downloads the checkpoint. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
+59
-5
@@ -67,6 +67,7 @@ from core import (
|
||||
find_ffmpeg,
|
||||
PracticalRifeEnv,
|
||||
FilmEnv,
|
||||
BimVfiEnv,
|
||||
SymlinkManager,
|
||||
OPTICAL_FLOW_PRESETS,
|
||||
)
|
||||
@@ -236,8 +237,12 @@ class DirectTransitionDialog(QDialog):
|
||||
self.method_combo = QComboBox()
|
||||
self.method_combo.addItem("RIFE (Fast, small motion)", DirectInterpolationMethod.RIFE)
|
||||
self.method_combo.addItem("FILM (Slow, large motion)", DirectInterpolationMethod.FILM)
|
||||
if method == DirectInterpolationMethod.FILM:
|
||||
self.method_combo.setCurrentIndex(1)
|
||||
self.method_combo.addItem("BiM-VFI (Best quality, slowest)", DirectInterpolationMethod.BIM_VFI)
|
||||
# Set current method
|
||||
for i in range(self.method_combo.count()):
|
||||
if self.method_combo.itemData(i) == method:
|
||||
self.method_combo.setCurrentIndex(i)
|
||||
break
|
||||
form_layout.addRow("Method:", self.method_combo)
|
||||
|
||||
# Frame count
|
||||
@@ -268,7 +273,8 @@ class DirectTransitionDialog(QDialog):
|
||||
# Explanation
|
||||
explain = QLabel(
|
||||
"RIFE: Fast AI interpolation, best for small motion and color shifts.\n"
|
||||
"FILM: Google Research model, better for large motion and scene gaps.\n\n"
|
||||
"FILM: Google Research model, better for large motion and scene gaps.\n"
|
||||
"BiM-VFI: CVPR 2025, best quality for non-uniform/complex motions.\n\n"
|
||||
"Generated frames bridge the gap between the last frame of this\n"
|
||||
"sequence and the first frame of the next MAIN sequence."
|
||||
)
|
||||
@@ -305,6 +311,7 @@ class DirectTransitionDialog(QDialog):
|
||||
|
||||
rife_ready = PracticalRifeEnv.is_setup()
|
||||
film_ready = FilmEnv.is_setup() if rife_ready else False
|
||||
bim_ready = BimVfiEnv.is_setup() if rife_ready else False
|
||||
|
||||
if method == DirectInterpolationMethod.RIFE:
|
||||
if rife_ready:
|
||||
@@ -316,13 +323,13 @@ class DirectTransitionDialog(QDialog):
|
||||
self.status_label.setStyleSheet("color: orange; font-size: 10px;")
|
||||
self.setup_btn.setVisible(True)
|
||||
self.setup_btn.setText("Setup PyTorch Environment")
|
||||
else: # FILM
|
||||
elif method == DirectInterpolationMethod.FILM:
|
||||
if film_ready:
|
||||
self.status_label.setText("FILM: Ready")
|
||||
self.status_label.setStyleSheet("color: green; font-size: 10px;")
|
||||
self.setup_btn.setVisible(False)
|
||||
elif rife_ready:
|
||||
self.status_label.setText("FILM: Package not installed")
|
||||
self.status_label.setText("FILM: Model not downloaded")
|
||||
self.status_label.setStyleSheet("color: orange; font-size: 10px;")
|
||||
self.setup_btn.setVisible(True)
|
||||
self.setup_btn.setText("Install FILM Package")
|
||||
@@ -331,6 +338,21 @@ class DirectTransitionDialog(QDialog):
|
||||
self.status_label.setStyleSheet("color: orange; font-size: 10px;")
|
||||
self.setup_btn.setVisible(True)
|
||||
self.setup_btn.setText("Setup PyTorch Environment")
|
||||
else: # BIM_VFI
|
||||
if bim_ready:
|
||||
self.status_label.setText("BiM-VFI: Ready")
|
||||
self.status_label.setStyleSheet("color: green; font-size: 10px;")
|
||||
self.setup_btn.setVisible(False)
|
||||
elif rife_ready:
|
||||
self.status_label.setText("BiM-VFI: Not installed (repo + model needed)")
|
||||
self.status_label.setStyleSheet("color: orange; font-size: 10px;")
|
||||
self.setup_btn.setVisible(True)
|
||||
self.setup_btn.setText("Install BiM-VFI")
|
||||
else:
|
||||
self.status_label.setText("BiM-VFI: Not installed (PyTorch required first)")
|
||||
self.status_label.setStyleSheet("color: orange; font-size: 10px;")
|
||||
self.setup_btn.setVisible(True)
|
||||
self.setup_btn.setText("Setup PyTorch Environment")
|
||||
|
||||
def _on_setup(self) -> None:
|
||||
"""Handle setup button click."""
|
||||
@@ -397,6 +419,38 @@ class DirectTransitionDialog(QDialog):
|
||||
)
|
||||
return
|
||||
|
||||
# If BiM-VFI selected and we need to install it
|
||||
if method == DirectInterpolationMethod.BIM_VFI and not BimVfiEnv.is_setup():
|
||||
progress = QProgressDialog(
|
||||
"Setting up BiM-VFI...", "Cancel", 0, 100, self
|
||||
)
|
||||
progress.setWindowTitle("Setup")
|
||||
progress.setWindowModality(Qt.WindowModality.WindowModal)
|
||||
progress.setMinimumDuration(0)
|
||||
progress.setValue(0)
|
||||
|
||||
def progress_cb(msg, pct):
|
||||
progress.setLabelText(msg)
|
||||
progress.setValue(pct)
|
||||
|
||||
def cancelled_check():
|
||||
QApplication.processEvents()
|
||||
return progress.wasCanceled()
|
||||
|
||||
success = BimVfiEnv.setup_bim_vfi(progress_cb, cancelled_check)
|
||||
progress.close()
|
||||
|
||||
if not success:
|
||||
if not cancelled_check():
|
||||
QMessageBox.warning(
|
||||
self, "Setup Failed",
|
||||
"Failed to set up BiM-VFI.\n\n"
|
||||
"If the checkpoint download failed, you can download it "
|
||||
"manually from Google Drive and place it at:\n"
|
||||
f"{BimVfiEnv.get_checkpoint_path()}"
|
||||
)
|
||||
return
|
||||
|
||||
self._update_status()
|
||||
|
||||
def _on_remove(self) -> None:
|
||||
|
||||
Reference in New Issue
Block a user