Cut panorama overlaps along seams instead of averaging them
The merge weighted every overlap pixel by its distance from each frame's edge, a 200 px linear cross-fade. Anything the frames disagreed on — parallax in the near foreground, grass in the wind, a walker — came out twice at half strength: a soft double edge at 1:1. dr_pano::seam picks, per output texel at proxy resolution, which frame a pixel comes from. Where a new frame overlaps the composite the cost is the gain-corrected difference plus local detail plus nearness to either frame's edge, taken as the worst over a small window, and the cut is a dynamic-programming path across the overlap. merge.wgsl weights each frame by its tent-filtered share of that map, a 64 px blend that follows the seam, with the edge feather kept as the fallback. The page's preview uses the same map, and examples/merge.rs takes --feather-only for comparison.
This commit is contained in:
@@ -6,6 +6,9 @@
|
||||
//! cargo run -p dr-ui --example merge --release -- --leave-out 3 fixtures/pano/2025-08-05/*.CR2
|
||||
//! ```
|
||||
//!
|
||||
//! `--feather-only` merges without seams — every overlap the feathered
|
||||
//! average — for comparing the two on the same set.
|
||||
//!
|
||||
//! `--leave-out N` unticks frame `N` once the first alignment is in, as the
|
||||
//! page's box would, so the job aligns again without it.
|
||||
//!
|
||||
@@ -25,6 +28,7 @@ fn main() {
|
||||
let mut fill = false;
|
||||
let mut wait_engines = false;
|
||||
let mut leave_out: Option<usize> = None;
|
||||
let mut seams = true;
|
||||
loop {
|
||||
match args.first().map(String::as_str) {
|
||||
Some("--out") => {
|
||||
@@ -39,6 +43,10 @@ fn main() {
|
||||
args.remove(0);
|
||||
leave_out = args.remove(0).parse().ok();
|
||||
}
|
||||
Some("--feather-only") => {
|
||||
args.remove(0);
|
||||
seams = false;
|
||||
}
|
||||
Some("--wait-engines") => {
|
||||
args.remove(0);
|
||||
wait_engines = true;
|
||||
@@ -101,6 +109,7 @@ fn main() {
|
||||
dr_ui::merge::MergeRequest::new(frames, dr_ui::merge::MergeDestination::Local(dir));
|
||||
// The filler from the shared models directory, as the app finds it.
|
||||
request.inpaint_model = dr_ui::merge::inpaint_model_path();
|
||||
request.seams = seams;
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
let (decide, decision) = std::sync::mpsc::channel();
|
||||
let cancel = dr_ui::merge::Cancel::default();
|
||||
|
||||
Reference in New Issue
Block a user