Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/aris/scripts/preprocess_sonar_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,14 @@ def main():
cap.release()
logger.info(f"Successfully processed {frame_count} frames")

# Frame 0 has no MOG2 background model on the subtractor's first apply(), so
# ~100% of pixels are flagged as motion and the red channel whites out. MOG2
# still learned from frame 0 above; here we replace frame 0's output with
# frame 1's so the whiteout never reaches the video, keeping the frame count
# and index alignment intact. See issue #107.
if len(processed_frames) > 1:
processed_frames[0] = processed_frames[1]

# Save the processed video
filepath_save.parent.mkdir(parents=True, exist_ok=True)
logger.info(f"Saving preprocessed video to: {filepath_save}")
Expand Down
24 changes: 22 additions & 2 deletions src/aris/scripts/stabilize_and_preprocess_sonar_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,22 @@ def main():
frame_idx = 0
frames_written = 0

# Frame 0 has no MOG2 background model on the subtractor's first apply(), so
# ~100% of pixels are flagged as motion and the red channel whites out. Feed
# frame 0 to MOG2 as usual (it still helps build the model), but emit frame
# 1's output in its place, duplicated, so the whiteout never reaches the video
# while the frame count and index alignment are preserved. See issue #107.
pending_first_output = [None]

def write_output(frame):
if frames_written == 0:
pending_first_output[0] = frame # stash frame 0; frame 1 will replace it
return
if pending_first_output[0] is not None:
video_writer.write(frame) # slot 0 <- frame 1's output
pending_first_output[0] = None
video_writer.write(frame)

logger.info(
"Processing frames with combined stabilization and preprocessing (memory-efficient)..."
)
Expand Down Expand Up @@ -441,7 +457,7 @@ def main():
)

# Write frame immediately (memory-efficient!)
video_writer.write(output_frame)
write_output(output_frame)
frames_written += 1
pbar.update(1)

Expand Down Expand Up @@ -497,7 +513,7 @@ def main():
output_frame = aris.preprocessing.create_visualization(
result.blurred, result.edges, result.motion
)
video_writer.write(output_frame)
write_output(output_frame)
frames_written += 1
pbar.update(1)

Expand All @@ -507,6 +523,10 @@ def main():
else:
break

# Degenerate single-frame clip: no frame 1 to substitute, so emit frame 0.
if pending_first_output[0] is not None:
video_writer.write(pending_first_output[0])

# Cleanup
cap.release()
video_writer.release()
Expand Down
Loading